// File generated from our OpenAPI spec
package com.stripe.param;

import com.google.gson.annotations.SerializedName;
import com.stripe.net.ApiRequestParams;
import com.stripe.param.common.EmptyParam;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.EqualsAndHashCode;
import lombok.Getter;

@Getter
@EqualsAndHashCode(callSuper = false)
public class SubscriptionUpdateParams extends ApiRequestParams {
  /**
   * A list of prices and quantities that will generate invoice items appended to the next invoice
   * for this subscription. You may pass up to 20 items.
   */
  @SerializedName("add_invoice_items")
  List<SubscriptionUpdateParams.AddInvoiceItem> addInvoiceItems;

  /**
   * A non-negative decimal between 0 and 100, with at most two decimal places. This represents the
   * percentage of the subscription invoice total that will be transferred to the application
   * owner's Stripe account. The request must be made by a platform account on a connected account
   * in order to set an application fee percentage. For more information, see the application fees
   * <a
   * href="https://stripe.com/docs/connect/subscriptions#collecting-fees-on-subscriptions">documentation</a>.
   */
  @SerializedName("application_fee_percent")
  Object applicationFeePercent;

  /**
   * Automatic tax settings for this subscription. We recommend you only include this parameter when
   * the existing value is being changed.
   */
  @SerializedName("automatic_tax")
  AutomaticTax automaticTax;

  /**
   * Either {@code now} or {@code unchanged}. Setting the value to {@code now} resets the
   * subscription's billing cycle anchor to the current time (in UTC). For more information, see the
   * billing cycle <a
   * href="https://stripe.com/docs/billing/subscriptions/billing-cycle">documentation</a>.
   */
  @SerializedName("billing_cycle_anchor")
  BillingCycleAnchor billingCycleAnchor;

  /**
   * Define thresholds at which an invoice will be sent, and the subscription advanced to a new
   * billing period. When updating, pass an empty string to remove previously-defined thresholds.
   */
  @SerializedName("billing_thresholds")
  Object billingThresholds;

  /**
   * A timestamp at which the subscription should cancel. If set to a date before the current period
   * ends, this will cause a proration if prorations have been enabled using {@code
   * proration_behavior}. If set during a future period, this will always cause a proration for that
   * period.
   */
  @SerializedName("cancel_at")
  Object cancelAt;

  /**
   * Indicate whether this subscription should cancel at the end of the current period ({@code
   * current_period_end}). Defaults to {@code false}.
   */
  @SerializedName("cancel_at_period_end")
  Boolean cancelAtPeriodEnd;

  /** Details about why this subscription was cancelled. */
  @SerializedName("cancellation_details")
  CancellationDetails cancellationDetails;

  /**
   * Either {@code charge_automatically}, or {@code send_invoice}. When charging automatically,
   * Stripe will attempt to pay this subscription at the end of the cycle using the default source
   * attached to the customer. When sending an invoice, Stripe will email your customer an invoice
   * with payment instructions and mark the subscription as {@code active}. Defaults to {@code
   * charge_automatically}.
   */
  @SerializedName("collection_method")
  CollectionMethod collectionMethod;

  /**
   * Number of days a customer has to pay invoices generated by this subscription. Valid only for
   * subscriptions where {@code collection_method} is set to {@code send_invoice}.
   */
  @SerializedName("days_until_due")
  Long daysUntilDue;

  /**
   * ID of the default payment method for the subscription. It must belong to the customer
   * associated with the subscription. This takes precedence over {@code default_source}. If neither
   * are set, invoices will use the customer's <a
   * href="https://stripe.com/docs/api/customers/object#customer_object-invoice_settings-default_payment_method">invoice_settings.default_payment_method</a>
   * or <a
   * href="https://stripe.com/docs/api/customers/object#customer_object-default_source">default_source</a>.
   */
  @SerializedName("default_payment_method")
  Object defaultPaymentMethod;

  /**
   * ID of the default payment source for the subscription. It must belong to the customer
   * associated with the subscription and be in a chargeable state. If {@code
   * default_payment_method} is also set, {@code default_payment_method} will take precedence. If
   * neither are set, invoices will use the customer's <a
   * href="https://stripe.com/docs/api/customers/object#customer_object-invoice_settings-default_payment_method">invoice_settings.default_payment_method</a>
   * or <a
   * href="https://stripe.com/docs/api/customers/object#customer_object-default_source">default_source</a>.
   */
  @SerializedName("default_source")
  Object defaultSource;

  /**
   * The tax rates that will apply to any subscription item that does not have {@code tax_rates}
   * set. Invoices created will have their {@code default_tax_rates} populated from the
   * subscription. Pass an empty string to remove previously-defined tax rates.
   */
  @SerializedName("default_tax_rates")
  Object defaultTaxRates;

  /**
   * The subscription's description, meant to be displayable to the customer. Use this field to
   * optionally store an explanation of the subscription for rendering in Stripe surfaces and
   * certain local payment methods UIs.
   */
  @SerializedName("description")
  Object description;

  /**
   * The coupons to redeem into discounts for the subscription. If not specified or empty, inherits
   * the discount from the subscription's customer.
   */
  @SerializedName("discounts")
  Object discounts;

  /** Specifies which fields in the response should be expanded. */
  @SerializedName("expand")
  List<String> expand;

  /**
   * Map of extra parameters for custom features not available in this client library. The content
   * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
   * key/value pair is serialized as if the key is a root-level field (serialized) name in this
   * param object. Effectively, this map is flattened to its parent instance.
   */
  @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
  Map<String, Object> extraParams;

  /** All invoices will be billed using the specified settings. */
  @SerializedName("invoice_settings")
  InvoiceSettings invoiceSettings;

  /** A list of up to 20 subscription items, each with an attached price. */
  @SerializedName("items")
  List<SubscriptionUpdateParams.Item> items;

  /**
   * Set of <a href="https://stripe.com/docs/api/metadata">key-value pairs</a> that you can attach
   * to an object. This can be useful for storing additional information about the object in a
   * structured format. Individual keys can be unset by posting an empty value to them. All keys can
   * be unset by posting an empty value to {@code metadata}.
   */
  @SerializedName("metadata")
  Object metadata;

  /**
   * Indicates if a customer is on or off-session while an invoice payment is attempted. Defaults to
   * {@code false} (on-session).
   */
  @SerializedName("off_session")
  Boolean offSession;

  /** The account on behalf of which to charge, for each of the subscription's invoices. */
  @SerializedName("on_behalf_of")
  Object onBehalfOf;

  /**
   * If specified, payment collection for this subscription will be paused. Note that the
   * subscription status will be unchanged and will not be updated to {@code paused}. Learn more
   * about <a href="https://stripe.com/docs/billing/subscriptions/pause-payment">pausing
   * collection</a>.
   */
  @SerializedName("pause_collection")
  Object pauseCollection;

  /**
   * Use {@code allow_incomplete} to transition the subscription to {@code status=past_due} if a
   * payment is required but cannot be paid. This allows you to manage scenarios where additional
   * user actions are needed to pay a subscription's invoice. For example, SCA regulation may
   * require 3DS authentication to complete payment. See the <a
   * href="https://stripe.com/docs/billing/migration/strong-customer-authentication">SCA Migration
   * Guide</a> for Billing to learn more. This is the default behavior.
   *
   * <p>Use {@code default_incomplete} to transition the subscription to {@code status=past_due}
   * when payment is required and await explicit confirmation of the invoice's payment intent. This
   * allows simpler management of scenarios where additional user actions are needed to pay a
   * subscription’s invoice. Such as failed payments, <a
   * href="https://stripe.com/docs/billing/migration/strong-customer-authentication">SCA
   * regulation</a>, or collecting a mandate for a bank debit payment method.
   *
   * <p>Use {@code pending_if_incomplete} to update the subscription using <a
   * href="https://stripe.com/docs/billing/subscriptions/pending-updates">pending updates</a>. When
   * you use {@code pending_if_incomplete} you can only pass the parameters <a
   * href="https://stripe.com/docs/billing/pending-updates-reference#supported-attributes">supported
   * by pending updates</a>.
   *
   * <p>Use {@code error_if_incomplete} if you want Stripe to return an HTTP 402 status code if a
   * subscription's invoice cannot be paid. For example, if a payment method requires 3DS
   * authentication due to SCA regulation and further user action is needed, this parameter does not
   * update the subscription and returns an error instead. This was the default behavior for API
   * versions prior to 2019-03-14. See the <a
   * href="https://docs.stripe.com/changelog/2019-03-14">changelog</a> to learn more.
   */
  @SerializedName("payment_behavior")
  PaymentBehavior paymentBehavior;

  /** Payment settings to pass to invoices created by the subscription. */
  @SerializedName("payment_settings")
  PaymentSettings paymentSettings;

  /**
   * Specifies an interval for how often to bill for any pending invoice items. It is analogous to
   * calling <a href="https://stripe.com/docs/api#create_invoice">Create an invoice</a> for the
   * given subscription at the specified interval.
   */
  @SerializedName("pending_invoice_item_interval")
  Object pendingInvoiceItemInterval;

  /**
   * Determines how to handle <a
   * href="https://stripe.com/docs/billing/subscriptions/prorations">prorations</a> when the billing
   * cycle changes (e.g., when switching plans, resetting {@code billing_cycle_anchor=now}, or
   * starting a trial), or if an item's {@code quantity} changes. The default value is {@code
   * create_prorations}.
   */
  @SerializedName("proration_behavior")
  ProrationBehavior prorationBehavior;

  /**
   * If set, prorations will be calculated as though the subscription was updated at the given time.
   * This can be used to apply exactly the same prorations that were previewed with the <a
   * href="https://stripe.com/docs/api/invoices/create_preview">create preview</a> endpoint. {@code
   * proration_date} can also be used to implement custom proration logic, such as prorating by day
   * instead of by second, by providing the time that you wish to use for proration calculations.
   */
  @SerializedName("proration_date")
  Long prorationDate;

  /**
   * If specified, the funds from the subscription's invoices will be transferred to the destination
   * and the ID of the resulting transfers will be found on the resulting charges. This will be
   * unset if you POST an empty value.
   */
  @SerializedName("transfer_data")
  Object transferData;

  /**
   * Unix timestamp representing the end of the trial period the customer will get before being
   * charged for the first time. This will always overwrite any trials that might apply via a
   * subscribed plan. If set, {@code trial_end} will override the default trial period of the plan
   * the customer is being subscribed to. The {@code billing_cycle_anchor} will be updated to the
   * {@code trial_end} value. The special value {@code now} can be provided to end the customer's
   * trial immediately. Can be at most two years from {@code billing_cycle_anchor}.
   */
  @SerializedName("trial_end")
  Object trialEnd;

  /**
   * Indicates if a plan's {@code trial_period_days} should be applied to the subscription. Setting
   * {@code trial_end} per subscription is preferred, and this defaults to {@code false}. Setting
   * this flag to {@code true} together with {@code trial_end} is not allowed. See <a
   * href="https://stripe.com/docs/billing/subscriptions/trials">Using trial periods on
   * subscriptions</a> to learn more.
   */
  @SerializedName("trial_from_plan")
  Boolean trialFromPlan;

  /** Settings related to subscription trials. */
  @SerializedName("trial_settings")
  TrialSettings trialSettings;

  private SubscriptionUpdateParams(
      List<SubscriptionUpdateParams.AddInvoiceItem> addInvoiceItems,
      Object applicationFeePercent,
      AutomaticTax automaticTax,
      BillingCycleAnchor billingCycleAnchor,
      Object billingThresholds,
      Object cancelAt,
      Boolean cancelAtPeriodEnd,
      CancellationDetails cancellationDetails,
      CollectionMethod collectionMethod,
      Long daysUntilDue,
      Object defaultPaymentMethod,
      Object defaultSource,
      Object defaultTaxRates,
      Object description,
      Object discounts,
      List<String> expand,
      Map<String, Object> extraParams,
      InvoiceSettings invoiceSettings,
      List<SubscriptionUpdateParams.Item> items,
      Object metadata,
      Boolean offSession,
      Object onBehalfOf,
      Object pauseCollection,
      PaymentBehavior paymentBehavior,
      PaymentSettings paymentSettings,
      Object pendingInvoiceItemInterval,
      ProrationBehavior prorationBehavior,
      Long prorationDate,
      Object transferData,
      Object trialEnd,
      Boolean trialFromPlan,
      TrialSettings trialSettings) {
    this.addInvoiceItems = addInvoiceItems;
    this.applicationFeePercent = applicationFeePercent;
    this.automaticTax = automaticTax;
    this.billingCycleAnchor = billingCycleAnchor;
    this.billingThresholds = billingThresholds;
    this.cancelAt = cancelAt;
    this.cancelAtPeriodEnd = cancelAtPeriodEnd;
    this.cancellationDetails = cancellationDetails;
    this.collectionMethod = collectionMethod;
    this.daysUntilDue = daysUntilDue;
    this.defaultPaymentMethod = defaultPaymentMethod;
    this.defaultSource = defaultSource;
    this.defaultTaxRates = defaultTaxRates;
    this.description = description;
    this.discounts = discounts;
    this.expand = expand;
    this.extraParams = extraParams;
    this.invoiceSettings = invoiceSettings;
    this.items = items;
    this.metadata = metadata;
    this.offSession = offSession;
    this.onBehalfOf = onBehalfOf;
    this.pauseCollection = pauseCollection;
    this.paymentBehavior = paymentBehavior;
    this.paymentSettings = paymentSettings;
    this.pendingInvoiceItemInterval = pendingInvoiceItemInterval;
    this.prorationBehavior = prorationBehavior;
    this.prorationDate = prorationDate;
    this.transferData = transferData;
    this.trialEnd = trialEnd;
    this.trialFromPlan = trialFromPlan;
    this.trialSettings = trialSettings;
  }

  public static Builder builder() {
    return new Builder();
  }

  public static class Builder {
    private List<SubscriptionUpdateParams.AddInvoiceItem> addInvoiceItems;

    private Object applicationFeePercent;

    private AutomaticTax automaticTax;

    private BillingCycleAnchor billingCycleAnchor;

    private Object billingThresholds;

    private Object cancelAt;

    private Boolean cancelAtPeriodEnd;

    private CancellationDetails cancellationDetails;

    private CollectionMethod collectionMethod;

    private Long daysUntilDue;

    private Object defaultPaymentMethod;

    private Object defaultSource;

    private Object defaultTaxRates;

    private Object description;

    private Object discounts;

    private List<String> expand;

    private Map<String, Object> extraParams;

    private InvoiceSettings invoiceSettings;

    private List<SubscriptionUpdateParams.Item> items;

    private Object metadata;

    private Boolean offSession;

    private Object onBehalfOf;

    private Object pauseCollection;

    private PaymentBehavior paymentBehavior;

    private PaymentSettings paymentSettings;

    private Object pendingInvoiceItemInterval;

    private ProrationBehavior prorationBehavior;

    private Long prorationDate;

    private Object transferData;

    private Object trialEnd;

    private Boolean trialFromPlan;

    private TrialSettings trialSettings;

    /** Finalize and obtain parameter instance from this builder. */
    public SubscriptionUpdateParams build() {
      return new SubscriptionUpdateParams(
          this.addInvoiceItems,
          this.applicationFeePercent,
          this.automaticTax,
          this.billingCycleAnchor,
          this.billingThresholds,
          this.cancelAt,
          this.cancelAtPeriodEnd,
          this.cancellationDetails,
          this.collectionMethod,
          this.daysUntilDue,
          this.defaultPaymentMethod,
          this.defaultSource,
          this.defaultTaxRates,
          this.description,
          this.discounts,
          this.expand,
          this.extraParams,
          this.invoiceSettings,
          this.items,
          this.metadata,
          this.offSession,
          this.onBehalfOf,
          this.pauseCollection,
          this.paymentBehavior,
          this.paymentSettings,
          this.pendingInvoiceItemInterval,
          this.prorationBehavior,
          this.prorationDate,
          this.transferData,
          this.trialEnd,
          this.trialFromPlan,
          this.trialSettings);
    }

    /**
     * Add an element to `addInvoiceItems` list. A list is initialized for the first `add/addAll`
     * call, and subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#addInvoiceItems} for the field documentation.
     */
    public Builder addAddInvoiceItem(SubscriptionUpdateParams.AddInvoiceItem element) {
      if (this.addInvoiceItems == null) {
        this.addInvoiceItems = new ArrayList<>();
      }
      this.addInvoiceItems.add(element);
      return this;
    }

    /**
     * Add all elements to `addInvoiceItems` list. A list is initialized for the first `add/addAll`
     * call, and subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#addInvoiceItems} for the field documentation.
     */
    public Builder addAllAddInvoiceItem(List<SubscriptionUpdateParams.AddInvoiceItem> elements) {
      if (this.addInvoiceItems == null) {
        this.addInvoiceItems = new ArrayList<>();
      }
      this.addInvoiceItems.addAll(elements);
      return this;
    }

    /**
     * A non-negative decimal between 0 and 100, with at most two decimal places. This represents
     * the percentage of the subscription invoice total that will be transferred to the application
     * owner's Stripe account. The request must be made by a platform account on a connected account
     * in order to set an application fee percentage. For more information, see the application fees
     * <a
     * href="https://stripe.com/docs/connect/subscriptions#collecting-fees-on-subscriptions">documentation</a>.
     */
    public Builder setApplicationFeePercent(BigDecimal applicationFeePercent) {
      this.applicationFeePercent = applicationFeePercent;
      return this;
    }

    /**
     * A non-negative decimal between 0 and 100, with at most two decimal places. This represents
     * the percentage of the subscription invoice total that will be transferred to the application
     * owner's Stripe account. The request must be made by a platform account on a connected account
     * in order to set an application fee percentage. For more information, see the application fees
     * <a
     * href="https://stripe.com/docs/connect/subscriptions#collecting-fees-on-subscriptions">documentation</a>.
     */
    public Builder setApplicationFeePercent(EmptyParam applicationFeePercent) {
      this.applicationFeePercent = applicationFeePercent;
      return this;
    }

    /**
     * Automatic tax settings for this subscription. We recommend you only include this parameter
     * when the existing value is being changed.
     */
    public Builder setAutomaticTax(SubscriptionUpdateParams.AutomaticTax automaticTax) {
      this.automaticTax = automaticTax;
      return this;
    }

    /**
     * Either {@code now} or {@code unchanged}. Setting the value to {@code now} resets the
     * subscription's billing cycle anchor to the current time (in UTC). For more information, see
     * the billing cycle <a
     * href="https://stripe.com/docs/billing/subscriptions/billing-cycle">documentation</a>.
     */
    public Builder setBillingCycleAnchor(
        SubscriptionUpdateParams.BillingCycleAnchor billingCycleAnchor) {
      this.billingCycleAnchor = billingCycleAnchor;
      return this;
    }

    /**
     * Define thresholds at which an invoice will be sent, and the subscription advanced to a new
     * billing period. When updating, pass an empty string to remove previously-defined thresholds.
     */
    public Builder setBillingThresholds(
        SubscriptionUpdateParams.BillingThresholds billingThresholds) {
      this.billingThresholds = billingThresholds;
      return this;
    }

    /**
     * Define thresholds at which an invoice will be sent, and the subscription advanced to a new
     * billing period. When updating, pass an empty string to remove previously-defined thresholds.
     */
    public Builder setBillingThresholds(EmptyParam billingThresholds) {
      this.billingThresholds = billingThresholds;
      return this;
    }

    /**
     * A timestamp at which the subscription should cancel. If set to a date before the current
     * period ends, this will cause a proration if prorations have been enabled using {@code
     * proration_behavior}. If set during a future period, this will always cause a proration for
     * that period.
     */
    public Builder setCancelAt(Long cancelAt) {
      this.cancelAt = cancelAt;
      return this;
    }

    /**
     * A timestamp at which the subscription should cancel. If set to a date before the current
     * period ends, this will cause a proration if prorations have been enabled using {@code
     * proration_behavior}. If set during a future period, this will always cause a proration for
     * that period.
     */
    public Builder setCancelAt(SubscriptionUpdateParams.CancelAt cancelAt) {
      this.cancelAt = cancelAt;
      return this;
    }

    /**
     * A timestamp at which the subscription should cancel. If set to a date before the current
     * period ends, this will cause a proration if prorations have been enabled using {@code
     * proration_behavior}. If set during a future period, this will always cause a proration for
     * that period.
     */
    public Builder setCancelAt(EmptyParam cancelAt) {
      this.cancelAt = cancelAt;
      return this;
    }

    /**
     * Indicate whether this subscription should cancel at the end of the current period ({@code
     * current_period_end}). Defaults to {@code false}.
     */
    public Builder setCancelAtPeriodEnd(Boolean cancelAtPeriodEnd) {
      this.cancelAtPeriodEnd = cancelAtPeriodEnd;
      return this;
    }

    /** Details about why this subscription was cancelled. */
    public Builder setCancellationDetails(
        SubscriptionUpdateParams.CancellationDetails cancellationDetails) {
      this.cancellationDetails = cancellationDetails;
      return this;
    }

    /**
     * Either {@code charge_automatically}, or {@code send_invoice}. When charging automatically,
     * Stripe will attempt to pay this subscription at the end of the cycle using the default source
     * attached to the customer. When sending an invoice, Stripe will email your customer an invoice
     * with payment instructions and mark the subscription as {@code active}. Defaults to {@code
     * charge_automatically}.
     */
    public Builder setCollectionMethod(SubscriptionUpdateParams.CollectionMethod collectionMethod) {
      this.collectionMethod = collectionMethod;
      return this;
    }

    /**
     * Number of days a customer has to pay invoices generated by this subscription. Valid only for
     * subscriptions where {@code collection_method} is set to {@code send_invoice}.
     */
    public Builder setDaysUntilDue(Long daysUntilDue) {
      this.daysUntilDue = daysUntilDue;
      return this;
    }

    /**
     * ID of the default payment method for the subscription. It must belong to the customer
     * associated with the subscription. This takes precedence over {@code default_source}. If
     * neither are set, invoices will use the customer's <a
     * href="https://stripe.com/docs/api/customers/object#customer_object-invoice_settings-default_payment_method">invoice_settings.default_payment_method</a>
     * or <a
     * href="https://stripe.com/docs/api/customers/object#customer_object-default_source">default_source</a>.
     */
    public Builder setDefaultPaymentMethod(String defaultPaymentMethod) {
      this.defaultPaymentMethod = defaultPaymentMethod;
      return this;
    }

    /**
     * ID of the default payment method for the subscription. It must belong to the customer
     * associated with the subscription. This takes precedence over {@code default_source}. If
     * neither are set, invoices will use the customer's <a
     * href="https://stripe.com/docs/api/customers/object#customer_object-invoice_settings-default_payment_method">invoice_settings.default_payment_method</a>
     * or <a
     * href="https://stripe.com/docs/api/customers/object#customer_object-default_source">default_source</a>.
     */
    public Builder setDefaultPaymentMethod(EmptyParam defaultPaymentMethod) {
      this.defaultPaymentMethod = defaultPaymentMethod;
      return this;
    }

    /**
     * ID of the default payment source for the subscription. It must belong to the customer
     * associated with the subscription and be in a chargeable state. If {@code
     * default_payment_method} is also set, {@code default_payment_method} will take precedence. If
     * neither are set, invoices will use the customer's <a
     * href="https://stripe.com/docs/api/customers/object#customer_object-invoice_settings-default_payment_method">invoice_settings.default_payment_method</a>
     * or <a
     * href="https://stripe.com/docs/api/customers/object#customer_object-default_source">default_source</a>.
     */
    public Builder setDefaultSource(String defaultSource) {
      this.defaultSource = defaultSource;
      return this;
    }

    /**
     * ID of the default payment source for the subscription. It must belong to the customer
     * associated with the subscription and be in a chargeable state. If {@code
     * default_payment_method} is also set, {@code default_payment_method} will take precedence. If
     * neither are set, invoices will use the customer's <a
     * href="https://stripe.com/docs/api/customers/object#customer_object-invoice_settings-default_payment_method">invoice_settings.default_payment_method</a>
     * or <a
     * href="https://stripe.com/docs/api/customers/object#customer_object-default_source">default_source</a>.
     */
    public Builder setDefaultSource(EmptyParam defaultSource) {
      this.defaultSource = defaultSource;
      return this;
    }

    /**
     * Add an element to `defaultTaxRates` list. A list is initialized for the first `add/addAll`
     * call, and subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#defaultTaxRates} for the field documentation.
     */
    @SuppressWarnings("unchecked")
    public Builder addDefaultTaxRate(String element) {
      if (this.defaultTaxRates == null || this.defaultTaxRates instanceof EmptyParam) {
        this.defaultTaxRates = new ArrayList<String>();
      }
      ((List<String>) this.defaultTaxRates).add(element);
      return this;
    }

    /**
     * Add all elements to `defaultTaxRates` list. A list is initialized for the first `add/addAll`
     * call, and subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#defaultTaxRates} for the field documentation.
     */
    @SuppressWarnings("unchecked")
    public Builder addAllDefaultTaxRate(List<String> elements) {
      if (this.defaultTaxRates == null || this.defaultTaxRates instanceof EmptyParam) {
        this.defaultTaxRates = new ArrayList<String>();
      }
      ((List<String>) this.defaultTaxRates).addAll(elements);
      return this;
    }

    /**
     * The tax rates that will apply to any subscription item that does not have {@code tax_rates}
     * set. Invoices created will have their {@code default_tax_rates} populated from the
     * subscription. Pass an empty string to remove previously-defined tax rates.
     */
    public Builder setDefaultTaxRates(EmptyParam defaultTaxRates) {
      this.defaultTaxRates = defaultTaxRates;
      return this;
    }

    /**
     * The tax rates that will apply to any subscription item that does not have {@code tax_rates}
     * set. Invoices created will have their {@code default_tax_rates} populated from the
     * subscription. Pass an empty string to remove previously-defined tax rates.
     */
    public Builder setDefaultTaxRates(List<String> defaultTaxRates) {
      this.defaultTaxRates = defaultTaxRates;
      return this;
    }

    /**
     * The subscription's description, meant to be displayable to the customer. Use this field to
     * optionally store an explanation of the subscription for rendering in Stripe surfaces and
     * certain local payment methods UIs.
     */
    public Builder setDescription(String description) {
      this.description = description;
      return this;
    }

    /**
     * The subscription's description, meant to be displayable to the customer. Use this field to
     * optionally store an explanation of the subscription for rendering in Stripe surfaces and
     * certain local payment methods UIs.
     */
    public Builder setDescription(EmptyParam description) {
      this.description = description;
      return this;
    }

    /**
     * Add an element to `discounts` list. A list is initialized for the first `add/addAll` call,
     * and subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#discounts} for the field documentation.
     */
    @SuppressWarnings("unchecked")
    public Builder addDiscount(SubscriptionUpdateParams.Discount element) {
      if (this.discounts == null || this.discounts instanceof EmptyParam) {
        this.discounts = new ArrayList<SubscriptionUpdateParams.Discount>();
      }
      ((List<SubscriptionUpdateParams.Discount>) this.discounts).add(element);
      return this;
    }

    /**
     * Add all elements to `discounts` list. A list is initialized for the first `add/addAll` call,
     * and subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#discounts} for the field documentation.
     */
    @SuppressWarnings("unchecked")
    public Builder addAllDiscount(List<SubscriptionUpdateParams.Discount> elements) {
      if (this.discounts == null || this.discounts instanceof EmptyParam) {
        this.discounts = new ArrayList<SubscriptionUpdateParams.Discount>();
      }
      ((List<SubscriptionUpdateParams.Discount>) this.discounts).addAll(elements);
      return this;
    }

    /**
     * The coupons to redeem into discounts for the subscription. If not specified or empty,
     * inherits the discount from the subscription's customer.
     */
    public Builder setDiscounts(EmptyParam discounts) {
      this.discounts = discounts;
      return this;
    }

    /**
     * The coupons to redeem into discounts for the subscription. If not specified or empty,
     * inherits the discount from the subscription's customer.
     */
    public Builder setDiscounts(List<SubscriptionUpdateParams.Discount> discounts) {
      this.discounts = discounts;
      return this;
    }

    /**
     * Add an element to `expand` list. A list is initialized for the first `add/addAll` call, and
     * subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#expand} for the field documentation.
     */
    public Builder addExpand(String element) {
      if (this.expand == null) {
        this.expand = new ArrayList<>();
      }
      this.expand.add(element);
      return this;
    }

    /**
     * Add all elements to `expand` list. A list is initialized for the first `add/addAll` call, and
     * subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#expand} for the field documentation.
     */
    public Builder addAllExpand(List<String> elements) {
      if (this.expand == null) {
        this.expand = new ArrayList<>();
      }
      this.expand.addAll(elements);
      return this;
    }

    /**
     * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
     * call, and subsequent calls add additional key/value pairs to the original map. See {@link
     * SubscriptionUpdateParams#extraParams} for the field documentation.
     */
    public Builder putExtraParam(String key, Object value) {
      if (this.extraParams == null) {
        this.extraParams = new HashMap<>();
      }
      this.extraParams.put(key, value);
      return this;
    }

    /**
     * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
     * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
     * See {@link SubscriptionUpdateParams#extraParams} for the field documentation.
     */
    public Builder putAllExtraParam(Map<String, Object> map) {
      if (this.extraParams == null) {
        this.extraParams = new HashMap<>();
      }
      this.extraParams.putAll(map);
      return this;
    }

    /** All invoices will be billed using the specified settings. */
    public Builder setInvoiceSettings(SubscriptionUpdateParams.InvoiceSettings invoiceSettings) {
      this.invoiceSettings = invoiceSettings;
      return this;
    }

    /**
     * Add an element to `items` list. A list is initialized for the first `add/addAll` call, and
     * subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#items} for the field documentation.
     */
    public Builder addItem(SubscriptionUpdateParams.Item element) {
      if (this.items == null) {
        this.items = new ArrayList<>();
      }
      this.items.add(element);
      return this;
    }

    /**
     * Add all elements to `items` list. A list is initialized for the first `add/addAll` call, and
     * subsequent calls adds additional elements to the original list. See {@link
     * SubscriptionUpdateParams#items} for the field documentation.
     */
    public Builder addAllItem(List<SubscriptionUpdateParams.Item> elements) {
      if (this.items == null) {
        this.items = new ArrayList<>();
      }
      this.items.addAll(elements);
      return this;
    }

    /**
     * Add a key/value pair to `metadata` map. A map is initialized for the first `put/putAll` call,
     * and subsequent calls add additional key/value pairs to the original map. See {@link
     * SubscriptionUpdateParams#metadata} for the field documentation.
     */
    @SuppressWarnings("unchecked")
    public Builder putMetadata(String key, String value) {
      if (this.metadata == null || this.metadata instanceof EmptyParam) {
        this.metadata = new HashMap<String, String>();
      }
      ((Map<String, String>) this.metadata).put(key, value);
      return this;
    }

    /**
     * Add all map key/value pairs to `metadata` map. A map is initialized for the first
     * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
     * See {@link SubscriptionUpdateParams#metadata} for the field documentation.
     */
    @SuppressWarnings("unchecked")
    public Builder putAllMetadata(Map<String, String> map) {
      if (this.metadata == null || this.metadata instanceof EmptyParam) {
        this.metadata = new HashMap<String, String>();
      }
      ((Map<String, String>) this.metadata).putAll(map);
      return this;
    }

    /**
     * Set of <a href="https://stripe.com/docs/api/metadata">key-value pairs</a> that you can attach
     * to an object. This can be useful for storing additional information about the object in a
     * structured format. Individual keys can be unset by posting an empty value to them. All keys
     * can be unset by posting an empty value to {@code metadata}.
     */
    public Builder setMetadata(EmptyParam metadata) {
      this.metadata = metadata;
      return this;
    }

    /**
     * Set of <a href="https://stripe.com/docs/api/metadata">key-value pairs</a> that you can attach
     * to an object. This can be useful for storing additional information about the object in a
     * structured format. Individual keys can be unset by posting an empty value to them. All keys
     * can be unset by posting an empty value to {@code metadata}.
     */
    public Builder setMetadata(Map<String, String> metadata) {
      this.metadata = metadata;
      return this;
    }

    /**
     * Indicates if a customer is on or off-session while an invoice payment is attempted. Defaults
     * to {@code false} (on-session).
     */
    public Builder setOffSession(Boolean offSession) {
      this.offSession = offSession;
      return this;
    }

    /** The account on behalf of which to charge, for each of the subscription's invoices. */
    public Builder setOnBehalfOf(String onBehalfOf) {
      this.onBehalfOf = onBehalfOf;
      return this;
    }

    /** The account on behalf of which to charge, for each of the subscription's invoices. */
    public Builder setOnBehalfOf(EmptyParam onBehalfOf) {
      this.onBehalfOf = onBehalfOf;
      return this;
    }

    /**
     * If specified, payment collection for this subscription will be paused. Note that the
     * subscription status will be unchanged and will not be updated to {@code paused}. Learn more
     * about <a href="https://stripe.com/docs/billing/subscriptions/pause-payment">pausing
     * collection</a>.
     */
    public Builder setPauseCollection(SubscriptionUpdateParams.PauseCollection pauseCollection) {
      this.pauseCollection = pauseCollection;
      return this;
    }

    /**
     * If specified, payment collection for this subscription will be paused. Note that the
     * subscription status will be unchanged and will not be updated to {@code paused}. Learn more
     * about <a href="https://stripe.com/docs/billing/subscriptions/pause-payment">pausing
     * collection</a>.
     */
    public Builder setPauseCollection(EmptyParam pauseCollection) {
      this.pauseCollection = pauseCollection;
      return this;
    }

    /**
     * Use {@code allow_incomplete} to transition the subscription to {@code status=past_due} if a
     * payment is required but cannot be paid. This allows you to manage scenarios where additional
     * user actions are needed to pay a subscription's invoice. For example, SCA regulation may
     * require 3DS authentication to complete payment. See the <a
     * href="https://stripe.com/docs/billing/migration/strong-customer-authentication">SCA Migration
     * Guide</a> for Billing to learn more. This is the default behavior.
     *
     * <p>Use {@code default_incomplete} to transition the subscription to {@code status=past_due}
     * when payment is required and await explicit confirmation of the invoice's payment intent.
     * This allows simpler management of scenarios where additional user actions are needed to pay a
     * subscription’s invoice. Such as failed payments, <a
     * href="https://stripe.com/docs/billing/migration/strong-customer-authentication">SCA
     * regulation</a>, or collecting a mandate for a bank debit payment method.
     *
     * <p>Use {@code pending_if_incomplete} to update the subscription using <a
     * href="https://stripe.com/docs/billing/subscriptions/pending-updates">pending updates</a>.
     * When you use {@code pending_if_incomplete} you can only pass the parameters <a
     * href="https://stripe.com/docs/billing/pending-updates-reference#supported-attributes">supported
     * by pending updates</a>.
     *
     * <p>Use {@code error_if_incomplete} if you want Stripe to return an HTTP 402 status code if a
     * subscription's invoice cannot be paid. For example, if a payment method requires 3DS
     * authentication due to SCA regulation and further user action is needed, this parameter does
     * not update the subscription and returns an error instead. This was the default behavior for
     * API versions prior to 2019-03-14. See the <a
     * href="https://docs.stripe.com/changelog/2019-03-14">changelog</a> to learn more.
     */
    public Builder setPaymentBehavior(SubscriptionUpdateParams.PaymentBehavior paymentBehavior) {
      this.paymentBehavior = paymentBehavior;
      return this;
    }

    /** Payment settings to pass to invoices created by the subscription. */
    public Builder setPaymentSettings(SubscriptionUpdateParams.PaymentSettings paymentSettings) {
      this.paymentSettings = paymentSettings;
      return this;
    }

    /**
     * Specifies an interval for how often to bill for any pending invoice items. It is analogous to
     * calling <a href="https://stripe.com/docs/api#create_invoice">Create an invoice</a> for the
     * given subscription at the specified interval.
     */
    public Builder setPendingInvoiceItemInterval(
        SubscriptionUpdateParams.PendingInvoiceItemInterval pendingInvoiceItemInterval) {
      this.pendingInvoiceItemInterval = pendingInvoiceItemInterval;
      return this;
    }

    /**
     * Specifies an interval for how often to bill for any pending invoice items. It is analogous to
     * calling <a href="https://stripe.com/docs/api#create_invoice">Create an invoice</a> for the
     * given subscription at the specified interval.
     */
    public Builder setPendingInvoiceItemInterval(EmptyParam pendingInvoiceItemInterval) {
      this.pendingInvoiceItemInterval = pendingInvoiceItemInterval;
      return this;
    }

    /**
     * Determines how to handle <a
     * href="https://stripe.com/docs/billing/subscriptions/prorations">prorations</a> when the
     * billing cycle changes (e.g., when switching plans, resetting {@code
     * billing_cycle_anchor=now}, or starting a trial), or if an item's {@code quantity} changes.
     * The default value is {@code create_prorations}.
     */
    public Builder setProrationBehavior(
        SubscriptionUpdateParams.ProrationBehavior prorationBehavior) {
      this.prorationBehavior = prorationBehavior;
      return this;
    }

    /**
     * If set, prorations will be calculated as though the subscription was updated at the given
     * time. This can be used to apply exactly the same prorations that were previewed with the <a
     * href="https://stripe.com/docs/api/invoices/create_preview">create preview</a> endpoint.
     * {@code proration_date} can also be used to implement custom proration logic, such as
     * prorating by day instead of by second, by providing the time that you wish to use for
     * proration calculations.
     */
    public Builder setProrationDate(Long prorationDate) {
      this.prorationDate = prorationDate;
      return this;
    }

    /**
     * If specified, the funds from the subscription's invoices will be transferred to the
     * destination and the ID of the resulting transfers will be found on the resulting charges.
     * This will be unset if you POST an empty value.
     */
    public Builder setTransferData(SubscriptionUpdateParams.TransferData transferData) {
      this.transferData = transferData;
      return this;
    }

    /**
     * If specified, the funds from the subscription's invoices will be transferred to the
     * destination and the ID of the resulting transfers will be found on the resulting charges.
     * This will be unset if you POST an empty value.
     */
    public Builder setTransferData(EmptyParam transferData) {
      this.transferData = transferData;
      return this;
    }

    /**
     * Unix timestamp representing the end of the trial period the customer will get before being
     * charged for the first time. This will always overwrite any trials that might apply via a
     * subscribed plan. If set, {@code trial_end} will override the default trial period of the plan
     * the customer is being subscribed to. The {@code billing_cycle_anchor} will be updated to the
     * {@code trial_end} value. The special value {@code now} can be provided to end the customer's
     * trial immediately. Can be at most two years from {@code billing_cycle_anchor}.
     */
    public Builder setTrialEnd(SubscriptionUpdateParams.TrialEnd trialEnd) {
      this.trialEnd = trialEnd;
      return this;
    }

    /**
     * Unix timestamp representing the end of the trial period the customer will get before being
     * charged for the first time. This will always overwrite any trials that might apply via a
     * subscribed plan. If set, {@code trial_end} will override the default trial period of the plan
     * the customer is being subscribed to. The {@code billing_cycle_anchor} will be updated to the
     * {@code trial_end} value. The special value {@code now} can be provided to end the customer's
     * trial immediately. Can be at most two years from {@code billing_cycle_anchor}.
     */
    public Builder setTrialEnd(Long trialEnd) {
      this.trialEnd = trialEnd;
      return this;
    }

    /**
     * Indicates if a plan's {@code trial_period_days} should be applied to the subscription.
     * Setting {@code trial_end} per subscription is preferred, and this defaults to {@code false}.
     * Setting this flag to {@code true} together with {@code trial_end} is not allowed. See <a
     * href="https://stripe.com/docs/billing/subscriptions/trials">Using trial periods on
     * subscriptions</a> to learn more.
     */
    public Builder setTrialFromPlan(Boolean trialFromPlan) {
      this.trialFromPlan = trialFromPlan;
      return this;
    }

    /** Settings related to subscription trials. */
    public Builder setTrialSettings(SubscriptionUpdateParams.TrialSettings trialSettings) {
      this.trialSettings = trialSettings;
      return this;
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class AddInvoiceItem {
    /** The coupons to redeem into discounts for the item. */
    @SerializedName("discounts")
    List<SubscriptionUpdateParams.AddInvoiceItem.Discount> discounts;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /**
     * Set of <a href="https://stripe.com/docs/api/metadata">key-value pairs</a> that you can attach
     * to an object. This can be useful for storing additional information about the object in a
     * structured format. Individual keys can be unset by posting an empty value to them. All keys
     * can be unset by posting an empty value to {@code metadata}.
     */
    @SerializedName("metadata")
    Map<String, String> metadata;

    /**
     * The period associated with this invoice item. If not set, {@code period.start.type} defaults
     * to {@code max_item_period_start} and {@code period.end.type} defaults to {@code
     * min_item_period_end}.
     */
    @SerializedName("period")
    Period period;

    /** The ID of the price object. One of {@code price} or {@code price_data} is required. */
    @SerializedName("price")
    Object price;

    /**
     * Data used to generate a new <a href="https://stripe.com/docs/api/prices">Price</a> object
     * inline. One of {@code price} or {@code price_data} is required.
     */
    @SerializedName("price_data")
    PriceData priceData;

    /** Quantity for this item. Defaults to 1. */
    @SerializedName("quantity")
    Long quantity;

    /**
     * The tax rates which apply to the item. When set, the {@code default_tax_rates} do not apply
     * to this item.
     */
    @SerializedName("tax_rates")
    Object taxRates;

    private AddInvoiceItem(
        List<SubscriptionUpdateParams.AddInvoiceItem.Discount> discounts,
        Map<String, Object> extraParams,
        Map<String, String> metadata,
        Period period,
        Object price,
        PriceData priceData,
        Long quantity,
        Object taxRates) {
      this.discounts = discounts;
      this.extraParams = extraParams;
      this.metadata = metadata;
      this.period = period;
      this.price = price;
      this.priceData = priceData;
      this.quantity = quantity;
      this.taxRates = taxRates;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private List<SubscriptionUpdateParams.AddInvoiceItem.Discount> discounts;

      private Map<String, Object> extraParams;

      private Map<String, String> metadata;

      private Period period;

      private Object price;

      private PriceData priceData;

      private Long quantity;

      private Object taxRates;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.AddInvoiceItem build() {
        return new SubscriptionUpdateParams.AddInvoiceItem(
            this.discounts,
            this.extraParams,
            this.metadata,
            this.period,
            this.price,
            this.priceData,
            this.quantity,
            this.taxRates);
      }

      /**
       * Add an element to `discounts` list. A list is initialized for the first `add/addAll` call,
       * and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.AddInvoiceItem#discounts} for the field documentation.
       */
      public Builder addDiscount(SubscriptionUpdateParams.AddInvoiceItem.Discount element) {
        if (this.discounts == null) {
          this.discounts = new ArrayList<>();
        }
        this.discounts.add(element);
        return this;
      }

      /**
       * Add all elements to `discounts` list. A list is initialized for the first `add/addAll`
       * call, and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.AddInvoiceItem#discounts} for the field documentation.
       */
      public Builder addAllDiscount(
          List<SubscriptionUpdateParams.AddInvoiceItem.Discount> elements) {
        if (this.discounts == null) {
          this.discounts = new ArrayList<>();
        }
        this.discounts.addAll(elements);
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.AddInvoiceItem#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.AddInvoiceItem#extraParams} for the field
       * documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /**
       * Add a key/value pair to `metadata` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.AddInvoiceItem#metadata} for the field documentation.
       */
      public Builder putMetadata(String key, String value) {
        if (this.metadata == null) {
          this.metadata = new HashMap<>();
        }
        this.metadata.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `metadata` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.AddInvoiceItem#metadata} for the field documentation.
       */
      public Builder putAllMetadata(Map<String, String> map) {
        if (this.metadata == null) {
          this.metadata = new HashMap<>();
        }
        this.metadata.putAll(map);
        return this;
      }

      /**
       * The period associated with this invoice item. If not set, {@code period.start.type}
       * defaults to {@code max_item_period_start} and {@code period.end.type} defaults to {@code
       * min_item_period_end}.
       */
      public Builder setPeriod(SubscriptionUpdateParams.AddInvoiceItem.Period period) {
        this.period = period;
        return this;
      }

      /** The ID of the price object. One of {@code price} or {@code price_data} is required. */
      public Builder setPrice(String price) {
        this.price = price;
        return this;
      }

      /** The ID of the price object. One of {@code price} or {@code price_data} is required. */
      public Builder setPrice(EmptyParam price) {
        this.price = price;
        return this;
      }

      /**
       * Data used to generate a new <a href="https://stripe.com/docs/api/prices">Price</a> object
       * inline. One of {@code price} or {@code price_data} is required.
       */
      public Builder setPriceData(SubscriptionUpdateParams.AddInvoiceItem.PriceData priceData) {
        this.priceData = priceData;
        return this;
      }

      /** Quantity for this item. Defaults to 1. */
      public Builder setQuantity(Long quantity) {
        this.quantity = quantity;
        return this;
      }

      /**
       * Add an element to `taxRates` list. A list is initialized for the first `add/addAll` call,
       * and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.AddInvoiceItem#taxRates} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addTaxRate(String element) {
        if (this.taxRates == null || this.taxRates instanceof EmptyParam) {
          this.taxRates = new ArrayList<String>();
        }
        ((List<String>) this.taxRates).add(element);
        return this;
      }

      /**
       * Add all elements to `taxRates` list. A list is initialized for the first `add/addAll` call,
       * and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.AddInvoiceItem#taxRates} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addAllTaxRate(List<String> elements) {
        if (this.taxRates == null || this.taxRates instanceof EmptyParam) {
          this.taxRates = new ArrayList<String>();
        }
        ((List<String>) this.taxRates).addAll(elements);
        return this;
      }

      /**
       * The tax rates which apply to the item. When set, the {@code default_tax_rates} do not apply
       * to this item.
       */
      public Builder setTaxRates(EmptyParam taxRates) {
        this.taxRates = taxRates;
        return this;
      }

      /**
       * The tax rates which apply to the item. When set, the {@code default_tax_rates} do not apply
       * to this item.
       */
      public Builder setTaxRates(List<String> taxRates) {
        this.taxRates = taxRates;
        return this;
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class Discount {
      /** ID of the coupon to create a new discount for. */
      @SerializedName("coupon")
      Object coupon;

      /** ID of an existing discount on the object (or one of its ancestors) to reuse. */
      @SerializedName("discount")
      Object discount;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /** ID of the promotion code to create a new discount for. */
      @SerializedName("promotion_code")
      Object promotionCode;

      private Discount(
          Object coupon, Object discount, Map<String, Object> extraParams, Object promotionCode) {
        this.coupon = coupon;
        this.discount = discount;
        this.extraParams = extraParams;
        this.promotionCode = promotionCode;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Object coupon;

        private Object discount;

        private Map<String, Object> extraParams;

        private Object promotionCode;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.AddInvoiceItem.Discount build() {
          return new SubscriptionUpdateParams.AddInvoiceItem.Discount(
              this.coupon, this.discount, this.extraParams, this.promotionCode);
        }

        /** ID of the coupon to create a new discount for. */
        public Builder setCoupon(String coupon) {
          this.coupon = coupon;
          return this;
        }

        /** ID of the coupon to create a new discount for. */
        public Builder setCoupon(EmptyParam coupon) {
          this.coupon = coupon;
          return this;
        }

        /** ID of an existing discount on the object (or one of its ancestors) to reuse. */
        public Builder setDiscount(String discount) {
          this.discount = discount;
          return this;
        }

        /** ID of an existing discount on the object (or one of its ancestors) to reuse. */
        public Builder setDiscount(EmptyParam discount) {
          this.discount = discount;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.Discount#extraParams} for the
         * field documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.Discount#extraParams} for the
         * field documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /** ID of the promotion code to create a new discount for. */
        public Builder setPromotionCode(String promotionCode) {
          this.promotionCode = promotionCode;
          return this;
        }

        /** ID of the promotion code to create a new discount for. */
        public Builder setPromotionCode(EmptyParam promotionCode) {
          this.promotionCode = promotionCode;
          return this;
        }
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class Period {
      /** <strong>Required.</strong> End of the invoice item period. */
      @SerializedName("end")
      End end;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /** <strong>Required.</strong> Start of the invoice item period. */
      @SerializedName("start")
      Start start;

      private Period(End end, Map<String, Object> extraParams, Start start) {
        this.end = end;
        this.extraParams = extraParams;
        this.start = start;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private End end;

        private Map<String, Object> extraParams;

        private Start start;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.AddInvoiceItem.Period build() {
          return new SubscriptionUpdateParams.AddInvoiceItem.Period(
              this.end, this.extraParams, this.start);
        }

        /** <strong>Required.</strong> End of the invoice item period. */
        public Builder setEnd(SubscriptionUpdateParams.AddInvoiceItem.Period.End end) {
          this.end = end;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.Period#extraParams} for the field
         * documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.Period#extraParams} for the field
         * documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /** <strong>Required.</strong> Start of the invoice item period. */
        public Builder setStart(SubscriptionUpdateParams.AddInvoiceItem.Period.Start start) {
          this.start = start;
          return this;
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class End {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /**
         * A precise Unix timestamp for the end of the invoice item period. Must be greater than or
         * equal to {@code period.start}.
         */
        @SerializedName("timestamp")
        Long timestamp;

        /**
         * <strong>Required.</strong> Select how to calculate the end of the invoice item period.
         */
        @SerializedName("type")
        Type type;

        private End(Map<String, Object> extraParams, Long timestamp, Type type) {
          this.extraParams = extraParams;
          this.timestamp = timestamp;
          this.type = type;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          private Long timestamp;

          private Type type;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.AddInvoiceItem.Period.End build() {
            return new SubscriptionUpdateParams.AddInvoiceItem.Period.End(
                this.extraParams, this.timestamp, this.type);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.Period.End#extraParams} for the
           * field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.Period.End#extraParams} for the
           * field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /**
           * A precise Unix timestamp for the end of the invoice item period. Must be greater than
           * or equal to {@code period.start}.
           */
          public Builder setTimestamp(Long timestamp) {
            this.timestamp = timestamp;
            return this;
          }

          /**
           * <strong>Required.</strong> Select how to calculate the end of the invoice item period.
           */
          public Builder setType(SubscriptionUpdateParams.AddInvoiceItem.Period.End.Type type) {
            this.type = type;
            return this;
          }
        }

        public enum Type implements ApiRequestParams.EnumParam {
          @SerializedName("min_item_period_end")
          MIN_ITEM_PERIOD_END("min_item_period_end"),

          @SerializedName("timestamp")
          TIMESTAMP("timestamp");

          @Getter(onMethod_ = {@Override})
          private final String value;

          Type(String value) {
            this.value = value;
          }
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class Start {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /**
         * A precise Unix timestamp for the start of the invoice item period. Must be less than or
         * equal to {@code period.end}.
         */
        @SerializedName("timestamp")
        Long timestamp;

        /**
         * <strong>Required.</strong> Select how to calculate the start of the invoice item period.
         */
        @SerializedName("type")
        Type type;

        private Start(Map<String, Object> extraParams, Long timestamp, Type type) {
          this.extraParams = extraParams;
          this.timestamp = timestamp;
          this.type = type;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          private Long timestamp;

          private Type type;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.AddInvoiceItem.Period.Start build() {
            return new SubscriptionUpdateParams.AddInvoiceItem.Period.Start(
                this.extraParams, this.timestamp, this.type);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.Period.Start#extraParams} for
           * the field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.Period.Start#extraParams} for
           * the field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /**
           * A precise Unix timestamp for the start of the invoice item period. Must be less than or
           * equal to {@code period.end}.
           */
          public Builder setTimestamp(Long timestamp) {
            this.timestamp = timestamp;
            return this;
          }

          /**
           * <strong>Required.</strong> Select how to calculate the start of the invoice item
           * period.
           */
          public Builder setType(SubscriptionUpdateParams.AddInvoiceItem.Period.Start.Type type) {
            this.type = type;
            return this;
          }
        }

        public enum Type implements ApiRequestParams.EnumParam {
          @SerializedName("max_item_period_start")
          MAX_ITEM_PERIOD_START("max_item_period_start"),

          @SerializedName("now")
          NOW("now"),

          @SerializedName("timestamp")
          TIMESTAMP("timestamp");

          @Getter(onMethod_ = {@Override})
          private final String value;

          Type(String value) {
            this.value = value;
          }
        }
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class PriceData {
      /**
       * <strong>Required.</strong> Three-letter <a
       * href="https://www.iso.org/iso-4217-currency-codes.html">ISO currency code</a>, in
       * lowercase. Must be a <a href="https://stripe.com/docs/currencies">supported currency</a>.
       */
      @SerializedName("currency")
      Object currency;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /**
       * <strong>Required.</strong> The ID of the <a
       * href="https://docs.stripe.com/api/products">Product</a> that this <a
       * href="https://docs.stripe.com/api/prices">Price</a> will belong to.
       */
      @SerializedName("product")
      Object product;

      /**
       * Only required if a <a
       * href="https://stripe.com/docs/tax/products-prices-tax-categories-tax-behavior#setting-a-default-tax-behavior-(recommended)">default
       * tax behavior</a> was not provided in the Stripe Tax settings. Specifies whether the price
       * is considered inclusive of taxes or exclusive of taxes. One of {@code inclusive}, {@code
       * exclusive}, or {@code unspecified}. Once specified as either {@code inclusive} or {@code
       * exclusive}, it cannot be changed.
       */
      @SerializedName("tax_behavior")
      TaxBehavior taxBehavior;

      /**
       * A positive integer in cents (or local equivalent) (or 0 for a free price) representing how
       * much to charge or a negative integer representing the amount to credit to the customer.
       */
      @SerializedName("unit_amount")
      Long unitAmount;

      /**
       * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
       * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
       * unit_amount_decimal} can be set.
       */
      @SerializedName("unit_amount_decimal")
      Object unitAmountDecimal;

      private PriceData(
          Object currency,
          Map<String, Object> extraParams,
          Object product,
          TaxBehavior taxBehavior,
          Long unitAmount,
          Object unitAmountDecimal) {
        this.currency = currency;
        this.extraParams = extraParams;
        this.product = product;
        this.taxBehavior = taxBehavior;
        this.unitAmount = unitAmount;
        this.unitAmountDecimal = unitAmountDecimal;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Object currency;

        private Map<String, Object> extraParams;

        private Object product;

        private TaxBehavior taxBehavior;

        private Long unitAmount;

        private Object unitAmountDecimal;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.AddInvoiceItem.PriceData build() {
          return new SubscriptionUpdateParams.AddInvoiceItem.PriceData(
              this.currency,
              this.extraParams,
              this.product,
              this.taxBehavior,
              this.unitAmount,
              this.unitAmountDecimal);
        }

        /**
         * <strong>Required.</strong> Three-letter <a
         * href="https://www.iso.org/iso-4217-currency-codes.html">ISO currency code</a>, in
         * lowercase. Must be a <a href="https://stripe.com/docs/currencies">supported currency</a>.
         */
        public Builder setCurrency(String currency) {
          this.currency = currency;
          return this;
        }

        /**
         * <strong>Required.</strong> Three-letter <a
         * href="https://www.iso.org/iso-4217-currency-codes.html">ISO currency code</a>, in
         * lowercase. Must be a <a href="https://stripe.com/docs/currencies">supported currency</a>.
         */
        public Builder setCurrency(EmptyParam currency) {
          this.currency = currency;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.PriceData#extraParams} for the
         * field documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.AddInvoiceItem.PriceData#extraParams} for the
         * field documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /**
         * <strong>Required.</strong> The ID of the <a
         * href="https://docs.stripe.com/api/products">Product</a> that this <a
         * href="https://docs.stripe.com/api/prices">Price</a> will belong to.
         */
        public Builder setProduct(String product) {
          this.product = product;
          return this;
        }

        /**
         * <strong>Required.</strong> The ID of the <a
         * href="https://docs.stripe.com/api/products">Product</a> that this <a
         * href="https://docs.stripe.com/api/prices">Price</a> will belong to.
         */
        public Builder setProduct(EmptyParam product) {
          this.product = product;
          return this;
        }

        /**
         * Only required if a <a
         * href="https://stripe.com/docs/tax/products-prices-tax-categories-tax-behavior#setting-a-default-tax-behavior-(recommended)">default
         * tax behavior</a> was not provided in the Stripe Tax settings. Specifies whether the price
         * is considered inclusive of taxes or exclusive of taxes. One of {@code inclusive}, {@code
         * exclusive}, or {@code unspecified}. Once specified as either {@code inclusive} or {@code
         * exclusive}, it cannot be changed.
         */
        public Builder setTaxBehavior(
            SubscriptionUpdateParams.AddInvoiceItem.PriceData.TaxBehavior taxBehavior) {
          this.taxBehavior = taxBehavior;
          return this;
        }

        /**
         * A positive integer in cents (or local equivalent) (or 0 for a free price) representing
         * how much to charge or a negative integer representing the amount to credit to the
         * customer.
         */
        public Builder setUnitAmount(Long unitAmount) {
          this.unitAmount = unitAmount;
          return this;
        }

        /**
         * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
         * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
         * unit_amount_decimal} can be set.
         */
        public Builder setUnitAmountDecimal(BigDecimal unitAmountDecimal) {
          this.unitAmountDecimal = unitAmountDecimal;
          return this;
        }

        /**
         * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
         * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
         * unit_amount_decimal} can be set.
         */
        public Builder setUnitAmountDecimal(EmptyParam unitAmountDecimal) {
          this.unitAmountDecimal = unitAmountDecimal;
          return this;
        }
      }

      public enum TaxBehavior implements ApiRequestParams.EnumParam {
        @SerializedName("exclusive")
        EXCLUSIVE("exclusive"),

        @SerializedName("inclusive")
        INCLUSIVE("inclusive"),

        @SerializedName("unspecified")
        UNSPECIFIED("unspecified");

        @Getter(onMethod_ = {@Override})
        private final String value;

        TaxBehavior(String value) {
          this.value = value;
        }
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class AutomaticTax {
    /**
     * <strong>Required.</strong> Enabled automatic tax calculation which will automatically compute
     * tax rates on all invoices generated by the subscription.
     */
    @SerializedName("enabled")
    Boolean enabled;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /**
     * The account that's liable for tax. If set, the business address and tax registrations
     * required to perform the tax calculation are loaded from this account. The tax transaction is
     * returned in the report of the connected account.
     */
    @SerializedName("liability")
    Liability liability;

    private AutomaticTax(Boolean enabled, Map<String, Object> extraParams, Liability liability) {
      this.enabled = enabled;
      this.extraParams = extraParams;
      this.liability = liability;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Boolean enabled;

      private Map<String, Object> extraParams;

      private Liability liability;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.AutomaticTax build() {
        return new SubscriptionUpdateParams.AutomaticTax(
            this.enabled, this.extraParams, this.liability);
      }

      /**
       * <strong>Required.</strong> Enabled automatic tax calculation which will automatically
       * compute tax rates on all invoices generated by the subscription.
       */
      public Builder setEnabled(Boolean enabled) {
        this.enabled = enabled;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.AutomaticTax#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.AutomaticTax#extraParams} for the field documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /**
       * The account that's liable for tax. If set, the business address and tax registrations
       * required to perform the tax calculation are loaded from this account. The tax transaction
       * is returned in the report of the connected account.
       */
      public Builder setLiability(SubscriptionUpdateParams.AutomaticTax.Liability liability) {
        this.liability = liability;
        return this;
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class Liability {
      /** The connected account being referenced when {@code type} is {@code account}. */
      @SerializedName("account")
      Object account;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /** <strong>Required.</strong> Type of the account referenced in the request. */
      @SerializedName("type")
      Type type;

      private Liability(Object account, Map<String, Object> extraParams, Type type) {
        this.account = account;
        this.extraParams = extraParams;
        this.type = type;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Object account;

        private Map<String, Object> extraParams;

        private Type type;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.AutomaticTax.Liability build() {
          return new SubscriptionUpdateParams.AutomaticTax.Liability(
              this.account, this.extraParams, this.type);
        }

        /** The connected account being referenced when {@code type} is {@code account}. */
        public Builder setAccount(String account) {
          this.account = account;
          return this;
        }

        /** The connected account being referenced when {@code type} is {@code account}. */
        public Builder setAccount(EmptyParam account) {
          this.account = account;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.AutomaticTax.Liability#extraParams} for the
         * field documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.AutomaticTax.Liability#extraParams} for the
         * field documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /** <strong>Required.</strong> Type of the account referenced in the request. */
        public Builder setType(SubscriptionUpdateParams.AutomaticTax.Liability.Type type) {
          this.type = type;
          return this;
        }
      }

      public enum Type implements ApiRequestParams.EnumParam {
        @SerializedName("account")
        ACCOUNT("account"),

        @SerializedName("self")
        SELF("self");

        @Getter(onMethod_ = {@Override})
        private final String value;

        Type(String value) {
          this.value = value;
        }
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class BillingThresholds {
    /** Monetary threshold that triggers the subscription to advance to a new billing period. */
    @SerializedName("amount_gte")
    Long amountGte;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /**
     * Indicates if the {@code billing_cycle_anchor} should be reset when a threshold is reached. If
     * true, {@code billing_cycle_anchor} will be updated to the date/time the threshold was last
     * reached; otherwise, the value will remain unchanged.
     */
    @SerializedName("reset_billing_cycle_anchor")
    Boolean resetBillingCycleAnchor;

    private BillingThresholds(
        Long amountGte, Map<String, Object> extraParams, Boolean resetBillingCycleAnchor) {
      this.amountGte = amountGte;
      this.extraParams = extraParams;
      this.resetBillingCycleAnchor = resetBillingCycleAnchor;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Long amountGte;

      private Map<String, Object> extraParams;

      private Boolean resetBillingCycleAnchor;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.BillingThresholds build() {
        return new SubscriptionUpdateParams.BillingThresholds(
            this.amountGte, this.extraParams, this.resetBillingCycleAnchor);
      }

      /** Monetary threshold that triggers the subscription to advance to a new billing period. */
      public Builder setAmountGte(Long amountGte) {
        this.amountGte = amountGte;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.BillingThresholds#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.BillingThresholds#extraParams} for the field
       * documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /**
       * Indicates if the {@code billing_cycle_anchor} should be reset when a threshold is reached.
       * If true, {@code billing_cycle_anchor} will be updated to the date/time the threshold was
       * last reached; otherwise, the value will remain unchanged.
       */
      public Builder setResetBillingCycleAnchor(Boolean resetBillingCycleAnchor) {
        this.resetBillingCycleAnchor = resetBillingCycleAnchor;
        return this;
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class CancellationDetails {
    /**
     * Additional comments about why the user canceled the subscription, if the subscription was
     * canceled explicitly by the user.
     */
    @SerializedName("comment")
    Object comment;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /**
     * The customer submitted reason for why they canceled, if the subscription was canceled
     * explicitly by the user.
     */
    @SerializedName("feedback")
    ApiRequestParams.EnumParam feedback;

    private CancellationDetails(
        Object comment, Map<String, Object> extraParams, ApiRequestParams.EnumParam feedback) {
      this.comment = comment;
      this.extraParams = extraParams;
      this.feedback = feedback;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Object comment;

      private Map<String, Object> extraParams;

      private ApiRequestParams.EnumParam feedback;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.CancellationDetails build() {
        return new SubscriptionUpdateParams.CancellationDetails(
            this.comment, this.extraParams, this.feedback);
      }

      /**
       * Additional comments about why the user canceled the subscription, if the subscription was
       * canceled explicitly by the user.
       */
      public Builder setComment(String comment) {
        this.comment = comment;
        return this;
      }

      /**
       * Additional comments about why the user canceled the subscription, if the subscription was
       * canceled explicitly by the user.
       */
      public Builder setComment(EmptyParam comment) {
        this.comment = comment;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.CancellationDetails#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.CancellationDetails#extraParams} for the field
       * documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /**
       * The customer submitted reason for why they canceled, if the subscription was canceled
       * explicitly by the user.
       */
      public Builder setFeedback(SubscriptionUpdateParams.CancellationDetails.Feedback feedback) {
        this.feedback = feedback;
        return this;
      }

      /**
       * The customer submitted reason for why they canceled, if the subscription was canceled
       * explicitly by the user.
       */
      public Builder setFeedback(EmptyParam feedback) {
        this.feedback = feedback;
        return this;
      }
    }

    public enum Feedback implements ApiRequestParams.EnumParam {
      @SerializedName("customer_service")
      CUSTOMER_SERVICE("customer_service"),

      @SerializedName("low_quality")
      LOW_QUALITY("low_quality"),

      @SerializedName("missing_features")
      MISSING_FEATURES("missing_features"),

      @SerializedName("other")
      OTHER("other"),

      @SerializedName("switched_service")
      SWITCHED_SERVICE("switched_service"),

      @SerializedName("too_complex")
      TOO_COMPLEX("too_complex"),

      @SerializedName("too_expensive")
      TOO_EXPENSIVE("too_expensive"),

      @SerializedName("unused")
      UNUSED("unused");

      @Getter(onMethod_ = {@Override})
      private final String value;

      Feedback(String value) {
        this.value = value;
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class Discount {
    /** ID of the coupon to create a new discount for. */
    @SerializedName("coupon")
    Object coupon;

    /** ID of an existing discount on the object (or one of its ancestors) to reuse. */
    @SerializedName("discount")
    Object discount;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /** ID of the promotion code to create a new discount for. */
    @SerializedName("promotion_code")
    Object promotionCode;

    private Discount(
        Object coupon, Object discount, Map<String, Object> extraParams, Object promotionCode) {
      this.coupon = coupon;
      this.discount = discount;
      this.extraParams = extraParams;
      this.promotionCode = promotionCode;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Object coupon;

      private Object discount;

      private Map<String, Object> extraParams;

      private Object promotionCode;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.Discount build() {
        return new SubscriptionUpdateParams.Discount(
            this.coupon, this.discount, this.extraParams, this.promotionCode);
      }

      /** ID of the coupon to create a new discount for. */
      public Builder setCoupon(String coupon) {
        this.coupon = coupon;
        return this;
      }

      /** ID of the coupon to create a new discount for. */
      public Builder setCoupon(EmptyParam coupon) {
        this.coupon = coupon;
        return this;
      }

      /** ID of an existing discount on the object (or one of its ancestors) to reuse. */
      public Builder setDiscount(String discount) {
        this.discount = discount;
        return this;
      }

      /** ID of an existing discount on the object (or one of its ancestors) to reuse. */
      public Builder setDiscount(EmptyParam discount) {
        this.discount = discount;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.Discount#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.Discount#extraParams} for the field documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /** ID of the promotion code to create a new discount for. */
      public Builder setPromotionCode(String promotionCode) {
        this.promotionCode = promotionCode;
        return this;
      }

      /** ID of the promotion code to create a new discount for. */
      public Builder setPromotionCode(EmptyParam promotionCode) {
        this.promotionCode = promotionCode;
        return this;
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class InvoiceSettings {
    /**
     * The account tax IDs associated with the subscription. Will be set on invoices generated by
     * the subscription.
     */
    @SerializedName("account_tax_ids")
    Object accountTaxIds;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /**
     * The connected account that issues the invoice. The invoice is presented with the branding and
     * support information of the specified account.
     */
    @SerializedName("issuer")
    Issuer issuer;

    private InvoiceSettings(Object accountTaxIds, Map<String, Object> extraParams, Issuer issuer) {
      this.accountTaxIds = accountTaxIds;
      this.extraParams = extraParams;
      this.issuer = issuer;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Object accountTaxIds;

      private Map<String, Object> extraParams;

      private Issuer issuer;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.InvoiceSettings build() {
        return new SubscriptionUpdateParams.InvoiceSettings(
            this.accountTaxIds, this.extraParams, this.issuer);
      }

      /**
       * Add an element to `accountTaxIds` list. A list is initialized for the first `add/addAll`
       * call, and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.InvoiceSettings#accountTaxIds} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addAccountTaxId(String element) {
        if (this.accountTaxIds == null || this.accountTaxIds instanceof EmptyParam) {
          this.accountTaxIds = new ArrayList<String>();
        }
        ((List<String>) this.accountTaxIds).add(element);
        return this;
      }

      /**
       * Add all elements to `accountTaxIds` list. A list is initialized for the first `add/addAll`
       * call, and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.InvoiceSettings#accountTaxIds} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addAllAccountTaxId(List<String> elements) {
        if (this.accountTaxIds == null || this.accountTaxIds instanceof EmptyParam) {
          this.accountTaxIds = new ArrayList<String>();
        }
        ((List<String>) this.accountTaxIds).addAll(elements);
        return this;
      }

      /**
       * The account tax IDs associated with the subscription. Will be set on invoices generated by
       * the subscription.
       */
      public Builder setAccountTaxIds(EmptyParam accountTaxIds) {
        this.accountTaxIds = accountTaxIds;
        return this;
      }

      /**
       * The account tax IDs associated with the subscription. Will be set on invoices generated by
       * the subscription.
       */
      public Builder setAccountTaxIds(List<String> accountTaxIds) {
        this.accountTaxIds = accountTaxIds;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.InvoiceSettings#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.InvoiceSettings#extraParams} for the field
       * documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /**
       * The connected account that issues the invoice. The invoice is presented with the branding
       * and support information of the specified account.
       */
      public Builder setIssuer(SubscriptionUpdateParams.InvoiceSettings.Issuer issuer) {
        this.issuer = issuer;
        return this;
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class Issuer {
      /** The connected account being referenced when {@code type} is {@code account}. */
      @SerializedName("account")
      Object account;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /** <strong>Required.</strong> Type of the account referenced in the request. */
      @SerializedName("type")
      Type type;

      private Issuer(Object account, Map<String, Object> extraParams, Type type) {
        this.account = account;
        this.extraParams = extraParams;
        this.type = type;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Object account;

        private Map<String, Object> extraParams;

        private Type type;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.InvoiceSettings.Issuer build() {
          return new SubscriptionUpdateParams.InvoiceSettings.Issuer(
              this.account, this.extraParams, this.type);
        }

        /** The connected account being referenced when {@code type} is {@code account}. */
        public Builder setAccount(String account) {
          this.account = account;
          return this;
        }

        /** The connected account being referenced when {@code type} is {@code account}. */
        public Builder setAccount(EmptyParam account) {
          this.account = account;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.InvoiceSettings.Issuer#extraParams} for the
         * field documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.InvoiceSettings.Issuer#extraParams} for the
         * field documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /** <strong>Required.</strong> Type of the account referenced in the request. */
        public Builder setType(SubscriptionUpdateParams.InvoiceSettings.Issuer.Type type) {
          this.type = type;
          return this;
        }
      }

      public enum Type implements ApiRequestParams.EnumParam {
        @SerializedName("account")
        ACCOUNT("account"),

        @SerializedName("self")
        SELF("self");

        @Getter(onMethod_ = {@Override})
        private final String value;

        Type(String value) {
          this.value = value;
        }
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class Item {
    /**
     * Define thresholds at which an invoice will be sent, and the subscription advanced to a new
     * billing period. Pass an empty string to remove previously-defined thresholds.
     */
    @SerializedName("billing_thresholds")
    Object billingThresholds;

    /**
     * Delete all usage for a given subscription item. You must pass this when deleting a usage
     * records subscription item. {@code clear_usage} has no effect if the plan has a billing meter
     * attached.
     */
    @SerializedName("clear_usage")
    Boolean clearUsage;

    /** A flag that, if set to {@code true}, will delete the specified item. */
    @SerializedName("deleted")
    Boolean deleted;

    /** The coupons to redeem into discounts for the subscription item. */
    @SerializedName("discounts")
    Object discounts;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /** Subscription item to update. */
    @SerializedName("id")
    Object id;

    /**
     * Set of <a href="https://stripe.com/docs/api/metadata">key-value pairs</a> that you can attach
     * to an object. This can be useful for storing additional information about the object in a
     * structured format. Individual keys can be unset by posting an empty value to them. All keys
     * can be unset by posting an empty value to {@code metadata}.
     */
    @SerializedName("metadata")
    Object metadata;

    /** Plan ID for this item, as a string. */
    @SerializedName("plan")
    Object plan;

    /**
     * The ID of the price object. One of {@code price} or {@code price_data} is required. When
     * changing a subscription item's price, {@code quantity} is set to 1 unless a {@code quantity}
     * parameter is provided.
     */
    @SerializedName("price")
    Object price;

    /**
     * Data used to generate a new <a href="https://stripe.com/docs/api/prices">Price</a> object
     * inline. One of {@code price} or {@code price_data} is required.
     */
    @SerializedName("price_data")
    PriceData priceData;

    /** Quantity for this item. */
    @SerializedName("quantity")
    Long quantity;

    /**
     * A list of <a href="https://stripe.com/docs/api/tax_rates">Tax Rate</a> ids. These Tax Rates
     * will override the <a
     * href="https://stripe.com/docs/api/subscriptions/create#create_subscription-default_tax_rates">{@code
     * default_tax_rates}</a> on the Subscription. When updating, pass an empty string to remove
     * previously-defined tax rates.
     */
    @SerializedName("tax_rates")
    Object taxRates;

    private Item(
        Object billingThresholds,
        Boolean clearUsage,
        Boolean deleted,
        Object discounts,
        Map<String, Object> extraParams,
        Object id,
        Object metadata,
        Object plan,
        Object price,
        PriceData priceData,
        Long quantity,
        Object taxRates) {
      this.billingThresholds = billingThresholds;
      this.clearUsage = clearUsage;
      this.deleted = deleted;
      this.discounts = discounts;
      this.extraParams = extraParams;
      this.id = id;
      this.metadata = metadata;
      this.plan = plan;
      this.price = price;
      this.priceData = priceData;
      this.quantity = quantity;
      this.taxRates = taxRates;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Object billingThresholds;

      private Boolean clearUsage;

      private Boolean deleted;

      private Object discounts;

      private Map<String, Object> extraParams;

      private Object id;

      private Object metadata;

      private Object plan;

      private Object price;

      private PriceData priceData;

      private Long quantity;

      private Object taxRates;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.Item build() {
        return new SubscriptionUpdateParams.Item(
            this.billingThresholds,
            this.clearUsage,
            this.deleted,
            this.discounts,
            this.extraParams,
            this.id,
            this.metadata,
            this.plan,
            this.price,
            this.priceData,
            this.quantity,
            this.taxRates);
      }

      /**
       * Define thresholds at which an invoice will be sent, and the subscription advanced to a new
       * billing period. Pass an empty string to remove previously-defined thresholds.
       */
      public Builder setBillingThresholds(
          SubscriptionUpdateParams.Item.BillingThresholds billingThresholds) {
        this.billingThresholds = billingThresholds;
        return this;
      }

      /**
       * Define thresholds at which an invoice will be sent, and the subscription advanced to a new
       * billing period. Pass an empty string to remove previously-defined thresholds.
       */
      public Builder setBillingThresholds(EmptyParam billingThresholds) {
        this.billingThresholds = billingThresholds;
        return this;
      }

      /**
       * Delete all usage for a given subscription item. You must pass this when deleting a usage
       * records subscription item. {@code clear_usage} has no effect if the plan has a billing
       * meter attached.
       */
      public Builder setClearUsage(Boolean clearUsage) {
        this.clearUsage = clearUsage;
        return this;
      }

      /** A flag that, if set to {@code true}, will delete the specified item. */
      public Builder setDeleted(Boolean deleted) {
        this.deleted = deleted;
        return this;
      }

      /**
       * Add an element to `discounts` list. A list is initialized for the first `add/addAll` call,
       * and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.Item#discounts} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addDiscount(SubscriptionUpdateParams.Item.Discount element) {
        if (this.discounts == null || this.discounts instanceof EmptyParam) {
          this.discounts = new ArrayList<SubscriptionUpdateParams.Item.Discount>();
        }
        ((List<SubscriptionUpdateParams.Item.Discount>) this.discounts).add(element);
        return this;
      }

      /**
       * Add all elements to `discounts` list. A list is initialized for the first `add/addAll`
       * call, and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.Item#discounts} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addAllDiscount(List<SubscriptionUpdateParams.Item.Discount> elements) {
        if (this.discounts == null || this.discounts instanceof EmptyParam) {
          this.discounts = new ArrayList<SubscriptionUpdateParams.Item.Discount>();
        }
        ((List<SubscriptionUpdateParams.Item.Discount>) this.discounts).addAll(elements);
        return this;
      }

      /** The coupons to redeem into discounts for the subscription item. */
      public Builder setDiscounts(EmptyParam discounts) {
        this.discounts = discounts;
        return this;
      }

      /** The coupons to redeem into discounts for the subscription item. */
      public Builder setDiscounts(List<SubscriptionUpdateParams.Item.Discount> discounts) {
        this.discounts = discounts;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.Item#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.Item#extraParams} for the field documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /** Subscription item to update. */
      public Builder setId(String id) {
        this.id = id;
        return this;
      }

      /** Subscription item to update. */
      public Builder setId(EmptyParam id) {
        this.id = id;
        return this;
      }

      /**
       * Add a key/value pair to `metadata` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.Item#metadata} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder putMetadata(String key, String value) {
        if (this.metadata == null || this.metadata instanceof EmptyParam) {
          this.metadata = new HashMap<String, String>();
        }
        ((Map<String, String>) this.metadata).put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `metadata` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.Item#metadata} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder putAllMetadata(Map<String, String> map) {
        if (this.metadata == null || this.metadata instanceof EmptyParam) {
          this.metadata = new HashMap<String, String>();
        }
        ((Map<String, String>) this.metadata).putAll(map);
        return this;
      }

      /**
       * Set of <a href="https://stripe.com/docs/api/metadata">key-value pairs</a> that you can
       * attach to an object. This can be useful for storing additional information about the object
       * in a structured format. Individual keys can be unset by posting an empty value to them. All
       * keys can be unset by posting an empty value to {@code metadata}.
       */
      public Builder setMetadata(EmptyParam metadata) {
        this.metadata = metadata;
        return this;
      }

      /**
       * Set of <a href="https://stripe.com/docs/api/metadata">key-value pairs</a> that you can
       * attach to an object. This can be useful for storing additional information about the object
       * in a structured format. Individual keys can be unset by posting an empty value to them. All
       * keys can be unset by posting an empty value to {@code metadata}.
       */
      public Builder setMetadata(Map<String, String> metadata) {
        this.metadata = metadata;
        return this;
      }

      /** Plan ID for this item, as a string. */
      public Builder setPlan(String plan) {
        this.plan = plan;
        return this;
      }

      /** Plan ID for this item, as a string. */
      public Builder setPlan(EmptyParam plan) {
        this.plan = plan;
        return this;
      }

      /**
       * The ID of the price object. One of {@code price} or {@code price_data} is required. When
       * changing a subscription item's price, {@code quantity} is set to 1 unless a {@code
       * quantity} parameter is provided.
       */
      public Builder setPrice(String price) {
        this.price = price;
        return this;
      }

      /**
       * The ID of the price object. One of {@code price} or {@code price_data} is required. When
       * changing a subscription item's price, {@code quantity} is set to 1 unless a {@code
       * quantity} parameter is provided.
       */
      public Builder setPrice(EmptyParam price) {
        this.price = price;
        return this;
      }

      /**
       * Data used to generate a new <a href="https://stripe.com/docs/api/prices">Price</a> object
       * inline. One of {@code price} or {@code price_data} is required.
       */
      public Builder setPriceData(SubscriptionUpdateParams.Item.PriceData priceData) {
        this.priceData = priceData;
        return this;
      }

      /** Quantity for this item. */
      public Builder setQuantity(Long quantity) {
        this.quantity = quantity;
        return this;
      }

      /**
       * Add an element to `taxRates` list. A list is initialized for the first `add/addAll` call,
       * and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.Item#taxRates} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addTaxRate(String element) {
        if (this.taxRates == null || this.taxRates instanceof EmptyParam) {
          this.taxRates = new ArrayList<String>();
        }
        ((List<String>) this.taxRates).add(element);
        return this;
      }

      /**
       * Add all elements to `taxRates` list. A list is initialized for the first `add/addAll` call,
       * and subsequent calls adds additional elements to the original list. See {@link
       * SubscriptionUpdateParams.Item#taxRates} for the field documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addAllTaxRate(List<String> elements) {
        if (this.taxRates == null || this.taxRates instanceof EmptyParam) {
          this.taxRates = new ArrayList<String>();
        }
        ((List<String>) this.taxRates).addAll(elements);
        return this;
      }

      /**
       * A list of <a href="https://stripe.com/docs/api/tax_rates">Tax Rate</a> ids. These Tax Rates
       * will override the <a
       * href="https://stripe.com/docs/api/subscriptions/create#create_subscription-default_tax_rates">{@code
       * default_tax_rates}</a> on the Subscription. When updating, pass an empty string to remove
       * previously-defined tax rates.
       */
      public Builder setTaxRates(EmptyParam taxRates) {
        this.taxRates = taxRates;
        return this;
      }

      /**
       * A list of <a href="https://stripe.com/docs/api/tax_rates">Tax Rate</a> ids. These Tax Rates
       * will override the <a
       * href="https://stripe.com/docs/api/subscriptions/create#create_subscription-default_tax_rates">{@code
       * default_tax_rates}</a> on the Subscription. When updating, pass an empty string to remove
       * previously-defined tax rates.
       */
      public Builder setTaxRates(List<String> taxRates) {
        this.taxRates = taxRates;
        return this;
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class BillingThresholds {
      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /**
       * <strong>Required.</strong> Number of units that meets the billing threshold to advance the
       * subscription to a new billing period (e.g., it takes 10 $5 units to meet a $50 <a
       * href="https://stripe.com/docs/api/subscriptions/update#update_subscription-billing_thresholds-amount_gte">monetary
       * threshold</a>)
       */
      @SerializedName("usage_gte")
      Long usageGte;

      private BillingThresholds(Map<String, Object> extraParams, Long usageGte) {
        this.extraParams = extraParams;
        this.usageGte = usageGte;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Map<String, Object> extraParams;

        private Long usageGte;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.Item.BillingThresholds build() {
          return new SubscriptionUpdateParams.Item.BillingThresholds(
              this.extraParams, this.usageGte);
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.Item.BillingThresholds#extraParams} for the
         * field documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.Item.BillingThresholds#extraParams} for the
         * field documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /**
         * <strong>Required.</strong> Number of units that meets the billing threshold to advance
         * the subscription to a new billing period (e.g., it takes 10 $5 units to meet a $50 <a
         * href="https://stripe.com/docs/api/subscriptions/update#update_subscription-billing_thresholds-amount_gte">monetary
         * threshold</a>)
         */
        public Builder setUsageGte(Long usageGte) {
          this.usageGte = usageGte;
          return this;
        }
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class Discount {
      /** ID of the coupon to create a new discount for. */
      @SerializedName("coupon")
      Object coupon;

      /** ID of an existing discount on the object (or one of its ancestors) to reuse. */
      @SerializedName("discount")
      Object discount;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /** ID of the promotion code to create a new discount for. */
      @SerializedName("promotion_code")
      Object promotionCode;

      private Discount(
          Object coupon, Object discount, Map<String, Object> extraParams, Object promotionCode) {
        this.coupon = coupon;
        this.discount = discount;
        this.extraParams = extraParams;
        this.promotionCode = promotionCode;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Object coupon;

        private Object discount;

        private Map<String, Object> extraParams;

        private Object promotionCode;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.Item.Discount build() {
          return new SubscriptionUpdateParams.Item.Discount(
              this.coupon, this.discount, this.extraParams, this.promotionCode);
        }

        /** ID of the coupon to create a new discount for. */
        public Builder setCoupon(String coupon) {
          this.coupon = coupon;
          return this;
        }

        /** ID of the coupon to create a new discount for. */
        public Builder setCoupon(EmptyParam coupon) {
          this.coupon = coupon;
          return this;
        }

        /** ID of an existing discount on the object (or one of its ancestors) to reuse. */
        public Builder setDiscount(String discount) {
          this.discount = discount;
          return this;
        }

        /** ID of an existing discount on the object (or one of its ancestors) to reuse. */
        public Builder setDiscount(EmptyParam discount) {
          this.discount = discount;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.Item.Discount#extraParams} for the field
         * documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.Item.Discount#extraParams} for the field
         * documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /** ID of the promotion code to create a new discount for. */
        public Builder setPromotionCode(String promotionCode) {
          this.promotionCode = promotionCode;
          return this;
        }

        /** ID of the promotion code to create a new discount for. */
        public Builder setPromotionCode(EmptyParam promotionCode) {
          this.promotionCode = promotionCode;
          return this;
        }
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class PriceData {
      /**
       * <strong>Required.</strong> Three-letter <a
       * href="https://www.iso.org/iso-4217-currency-codes.html">ISO currency code</a>, in
       * lowercase. Must be a <a href="https://stripe.com/docs/currencies">supported currency</a>.
       */
      @SerializedName("currency")
      Object currency;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /**
       * <strong>Required.</strong> The ID of the <a
       * href="https://docs.stripe.com/api/products">Product</a> that this <a
       * href="https://docs.stripe.com/api/prices">Price</a> will belong to.
       */
      @SerializedName("product")
      Object product;

      /**
       * <strong>Required.</strong> The recurring components of a price such as {@code interval} and
       * {@code interval_count}.
       */
      @SerializedName("recurring")
      Recurring recurring;

      /**
       * Only required if a <a
       * href="https://stripe.com/docs/tax/products-prices-tax-categories-tax-behavior#setting-a-default-tax-behavior-(recommended)">default
       * tax behavior</a> was not provided in the Stripe Tax settings. Specifies whether the price
       * is considered inclusive of taxes or exclusive of taxes. One of {@code inclusive}, {@code
       * exclusive}, or {@code unspecified}. Once specified as either {@code inclusive} or {@code
       * exclusive}, it cannot be changed.
       */
      @SerializedName("tax_behavior")
      TaxBehavior taxBehavior;

      /**
       * A positive integer in cents (or local equivalent) (or 0 for a free price) representing how
       * much to charge.
       */
      @SerializedName("unit_amount")
      Long unitAmount;

      /**
       * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
       * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
       * unit_amount_decimal} can be set.
       */
      @SerializedName("unit_amount_decimal")
      Object unitAmountDecimal;

      private PriceData(
          Object currency,
          Map<String, Object> extraParams,
          Object product,
          Recurring recurring,
          TaxBehavior taxBehavior,
          Long unitAmount,
          Object unitAmountDecimal) {
        this.currency = currency;
        this.extraParams = extraParams;
        this.product = product;
        this.recurring = recurring;
        this.taxBehavior = taxBehavior;
        this.unitAmount = unitAmount;
        this.unitAmountDecimal = unitAmountDecimal;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Object currency;

        private Map<String, Object> extraParams;

        private Object product;

        private Recurring recurring;

        private TaxBehavior taxBehavior;

        private Long unitAmount;

        private Object unitAmountDecimal;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.Item.PriceData build() {
          return new SubscriptionUpdateParams.Item.PriceData(
              this.currency,
              this.extraParams,
              this.product,
              this.recurring,
              this.taxBehavior,
              this.unitAmount,
              this.unitAmountDecimal);
        }

        /**
         * <strong>Required.</strong> Three-letter <a
         * href="https://www.iso.org/iso-4217-currency-codes.html">ISO currency code</a>, in
         * lowercase. Must be a <a href="https://stripe.com/docs/currencies">supported currency</a>.
         */
        public Builder setCurrency(String currency) {
          this.currency = currency;
          return this;
        }

        /**
         * <strong>Required.</strong> Three-letter <a
         * href="https://www.iso.org/iso-4217-currency-codes.html">ISO currency code</a>, in
         * lowercase. Must be a <a href="https://stripe.com/docs/currencies">supported currency</a>.
         */
        public Builder setCurrency(EmptyParam currency) {
          this.currency = currency;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.Item.PriceData#extraParams} for the field
         * documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.Item.PriceData#extraParams} for the field
         * documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /**
         * <strong>Required.</strong> The ID of the <a
         * href="https://docs.stripe.com/api/products">Product</a> that this <a
         * href="https://docs.stripe.com/api/prices">Price</a> will belong to.
         */
        public Builder setProduct(String product) {
          this.product = product;
          return this;
        }

        /**
         * <strong>Required.</strong> The ID of the <a
         * href="https://docs.stripe.com/api/products">Product</a> that this <a
         * href="https://docs.stripe.com/api/prices">Price</a> will belong to.
         */
        public Builder setProduct(EmptyParam product) {
          this.product = product;
          return this;
        }

        /**
         * <strong>Required.</strong> The recurring components of a price such as {@code interval}
         * and {@code interval_count}.
         */
        public Builder setRecurring(SubscriptionUpdateParams.Item.PriceData.Recurring recurring) {
          this.recurring = recurring;
          return this;
        }

        /**
         * Only required if a <a
         * href="https://stripe.com/docs/tax/products-prices-tax-categories-tax-behavior#setting-a-default-tax-behavior-(recommended)">default
         * tax behavior</a> was not provided in the Stripe Tax settings. Specifies whether the price
         * is considered inclusive of taxes or exclusive of taxes. One of {@code inclusive}, {@code
         * exclusive}, or {@code unspecified}. Once specified as either {@code inclusive} or {@code
         * exclusive}, it cannot be changed.
         */
        public Builder setTaxBehavior(
            SubscriptionUpdateParams.Item.PriceData.TaxBehavior taxBehavior) {
          this.taxBehavior = taxBehavior;
          return this;
        }

        /**
         * A positive integer in cents (or local equivalent) (or 0 for a free price) representing
         * how much to charge.
         */
        public Builder setUnitAmount(Long unitAmount) {
          this.unitAmount = unitAmount;
          return this;
        }

        /**
         * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
         * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
         * unit_amount_decimal} can be set.
         */
        public Builder setUnitAmountDecimal(BigDecimal unitAmountDecimal) {
          this.unitAmountDecimal = unitAmountDecimal;
          return this;
        }

        /**
         * Same as {@code unit_amount}, but accepts a decimal value in cents (or local equivalent)
         * with at most 12 decimal places. Only one of {@code unit_amount} and {@code
         * unit_amount_decimal} can be set.
         */
        public Builder setUnitAmountDecimal(EmptyParam unitAmountDecimal) {
          this.unitAmountDecimal = unitAmountDecimal;
          return this;
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class Recurring {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /**
         * <strong>Required.</strong> Specifies billing frequency. Either {@code day}, {@code week},
         * {@code month} or {@code year}.
         */
        @SerializedName("interval")
        Interval interval;

        /**
         * The number of intervals between subscription billings. For example, {@code
         * interval=month} and {@code interval_count=3} bills every 3 months. Maximum of three years
         * interval allowed (3 years, 36 months, or 156 weeks).
         */
        @SerializedName("interval_count")
        Long intervalCount;

        private Recurring(Map<String, Object> extraParams, Interval interval, Long intervalCount) {
          this.extraParams = extraParams;
          this.interval = interval;
          this.intervalCount = intervalCount;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          private Interval interval;

          private Long intervalCount;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.Item.PriceData.Recurring build() {
            return new SubscriptionUpdateParams.Item.PriceData.Recurring(
                this.extraParams, this.interval, this.intervalCount);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link SubscriptionUpdateParams.Item.PriceData.Recurring#extraParams} for the
           * field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link SubscriptionUpdateParams.Item.PriceData.Recurring#extraParams} for the
           * field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /**
           * <strong>Required.</strong> Specifies billing frequency. Either {@code day}, {@code
           * week}, {@code month} or {@code year}.
           */
          public Builder setInterval(
              SubscriptionUpdateParams.Item.PriceData.Recurring.Interval interval) {
            this.interval = interval;
            return this;
          }

          /**
           * The number of intervals between subscription billings. For example, {@code
           * interval=month} and {@code interval_count=3} bills every 3 months. Maximum of three
           * years interval allowed (3 years, 36 months, or 156 weeks).
           */
          public Builder setIntervalCount(Long intervalCount) {
            this.intervalCount = intervalCount;
            return this;
          }
        }

        public enum Interval implements ApiRequestParams.EnumParam {
          @SerializedName("day")
          DAY("day"),

          @SerializedName("month")
          MONTH("month"),

          @SerializedName("week")
          WEEK("week"),

          @SerializedName("year")
          YEAR("year");

          @Getter(onMethod_ = {@Override})
          private final String value;

          Interval(String value) {
            this.value = value;
          }
        }
      }

      public enum TaxBehavior implements ApiRequestParams.EnumParam {
        @SerializedName("exclusive")
        EXCLUSIVE("exclusive"),

        @SerializedName("inclusive")
        INCLUSIVE("inclusive"),

        @SerializedName("unspecified")
        UNSPECIFIED("unspecified");

        @Getter(onMethod_ = {@Override})
        private final String value;

        TaxBehavior(String value) {
          this.value = value;
        }
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class PauseCollection {
    /**
     * <strong>Required.</strong> The payment collection behavior for this subscription while
     * paused. One of {@code keep_as_draft}, {@code mark_uncollectible}, or {@code void}.
     */
    @SerializedName("behavior")
    Behavior behavior;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /** The time after which the subscription will resume collecting payments. */
    @SerializedName("resumes_at")
    Long resumesAt;

    private PauseCollection(Behavior behavior, Map<String, Object> extraParams, Long resumesAt) {
      this.behavior = behavior;
      this.extraParams = extraParams;
      this.resumesAt = resumesAt;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Behavior behavior;

      private Map<String, Object> extraParams;

      private Long resumesAt;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.PauseCollection build() {
        return new SubscriptionUpdateParams.PauseCollection(
            this.behavior, this.extraParams, this.resumesAt);
      }

      /**
       * <strong>Required.</strong> The payment collection behavior for this subscription while
       * paused. One of {@code keep_as_draft}, {@code mark_uncollectible}, or {@code void}.
       */
      public Builder setBehavior(SubscriptionUpdateParams.PauseCollection.Behavior behavior) {
        this.behavior = behavior;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.PauseCollection#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.PauseCollection#extraParams} for the field
       * documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /** The time after which the subscription will resume collecting payments. */
      public Builder setResumesAt(Long resumesAt) {
        this.resumesAt = resumesAt;
        return this;
      }
    }

    public enum Behavior implements ApiRequestParams.EnumParam {
      @SerializedName("keep_as_draft")
      KEEP_AS_DRAFT("keep_as_draft"),

      @SerializedName("mark_uncollectible")
      MARK_UNCOLLECTIBLE("mark_uncollectible"),

      @SerializedName("void")
      VOID("void");

      @Getter(onMethod_ = {@Override})
      private final String value;

      Behavior(String value) {
        this.value = value;
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class PaymentSettings {
    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /** Payment-method-specific configuration to provide to invoices created by the subscription. */
    @SerializedName("payment_method_options")
    PaymentMethodOptions paymentMethodOptions;

    /**
     * The list of payment method types (e.g. card) to provide to the invoice’s PaymentIntent. If
     * not set, Stripe attempts to automatically determine the types to use by looking at the
     * invoice’s default payment method, the subscription’s default payment method, the customer’s
     * default payment method, and your <a
     * href="https://dashboard.stripe.com/settings/billing/invoice">invoice template settings</a>.
     * Should not be specified with payment_method_configuration
     */
    @SerializedName("payment_method_types")
    Object paymentMethodTypes;

    /**
     * Configure whether Stripe updates {@code subscription.default_payment_method} when payment
     * succeeds. Defaults to {@code off} if unspecified.
     */
    @SerializedName("save_default_payment_method")
    SaveDefaultPaymentMethod saveDefaultPaymentMethod;

    private PaymentSettings(
        Map<String, Object> extraParams,
        PaymentMethodOptions paymentMethodOptions,
        Object paymentMethodTypes,
        SaveDefaultPaymentMethod saveDefaultPaymentMethod) {
      this.extraParams = extraParams;
      this.paymentMethodOptions = paymentMethodOptions;
      this.paymentMethodTypes = paymentMethodTypes;
      this.saveDefaultPaymentMethod = saveDefaultPaymentMethod;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Map<String, Object> extraParams;

      private PaymentMethodOptions paymentMethodOptions;

      private Object paymentMethodTypes;

      private SaveDefaultPaymentMethod saveDefaultPaymentMethod;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.PaymentSettings build() {
        return new SubscriptionUpdateParams.PaymentSettings(
            this.extraParams,
            this.paymentMethodOptions,
            this.paymentMethodTypes,
            this.saveDefaultPaymentMethod);
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.PaymentSettings#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.PaymentSettings#extraParams} for the field
       * documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /**
       * Payment-method-specific configuration to provide to invoices created by the subscription.
       */
      public Builder setPaymentMethodOptions(
          SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions paymentMethodOptions) {
        this.paymentMethodOptions = paymentMethodOptions;
        return this;
      }

      /**
       * Add an element to `paymentMethodTypes` list. A list is initialized for the first
       * `add/addAll` call, and subsequent calls adds additional elements to the original list. See
       * {@link SubscriptionUpdateParams.PaymentSettings#paymentMethodTypes} for the field
       * documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addPaymentMethodType(
          SubscriptionUpdateParams.PaymentSettings.PaymentMethodType element) {
        if (this.paymentMethodTypes == null || this.paymentMethodTypes instanceof EmptyParam) {
          this.paymentMethodTypes =
              new ArrayList<SubscriptionUpdateParams.PaymentSettings.PaymentMethodType>();
        }
        ((List<SubscriptionUpdateParams.PaymentSettings.PaymentMethodType>) this.paymentMethodTypes)
            .add(element);
        return this;
      }

      /**
       * Add all elements to `paymentMethodTypes` list. A list is initialized for the first
       * `add/addAll` call, and subsequent calls adds additional elements to the original list. See
       * {@link SubscriptionUpdateParams.PaymentSettings#paymentMethodTypes} for the field
       * documentation.
       */
      @SuppressWarnings("unchecked")
      public Builder addAllPaymentMethodType(
          List<SubscriptionUpdateParams.PaymentSettings.PaymentMethodType> elements) {
        if (this.paymentMethodTypes == null || this.paymentMethodTypes instanceof EmptyParam) {
          this.paymentMethodTypes =
              new ArrayList<SubscriptionUpdateParams.PaymentSettings.PaymentMethodType>();
        }
        ((List<SubscriptionUpdateParams.PaymentSettings.PaymentMethodType>) this.paymentMethodTypes)
            .addAll(elements);
        return this;
      }

      /**
       * The list of payment method types (e.g. card) to provide to the invoice’s PaymentIntent. If
       * not set, Stripe attempts to automatically determine the types to use by looking at the
       * invoice’s default payment method, the subscription’s default payment method, the customer’s
       * default payment method, and your <a
       * href="https://dashboard.stripe.com/settings/billing/invoice">invoice template settings</a>.
       * Should not be specified with payment_method_configuration
       */
      public Builder setPaymentMethodTypes(EmptyParam paymentMethodTypes) {
        this.paymentMethodTypes = paymentMethodTypes;
        return this;
      }

      /**
       * The list of payment method types (e.g. card) to provide to the invoice’s PaymentIntent. If
       * not set, Stripe attempts to automatically determine the types to use by looking at the
       * invoice’s default payment method, the subscription’s default payment method, the customer’s
       * default payment method, and your <a
       * href="https://dashboard.stripe.com/settings/billing/invoice">invoice template settings</a>.
       * Should not be specified with payment_method_configuration
       */
      public Builder setPaymentMethodTypes(
          List<SubscriptionUpdateParams.PaymentSettings.PaymentMethodType> paymentMethodTypes) {
        this.paymentMethodTypes = paymentMethodTypes;
        return this;
      }

      /**
       * Configure whether Stripe updates {@code subscription.default_payment_method} when payment
       * succeeds. Defaults to {@code off} if unspecified.
       */
      public Builder setSaveDefaultPaymentMethod(
          SubscriptionUpdateParams.PaymentSettings.SaveDefaultPaymentMethod
              saveDefaultPaymentMethod) {
        this.saveDefaultPaymentMethod = saveDefaultPaymentMethod;
        return this;
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class PaymentMethodOptions {
      /**
       * This sub-hash contains details about the Canadian pre-authorized debit payment method
       * options to pass to the invoice’s PaymentIntent.
       */
      @SerializedName("acss_debit")
      Object acssDebit;

      /**
       * This sub-hash contains details about the Bancontact payment method options to pass to the
       * invoice’s PaymentIntent.
       */
      @SerializedName("bancontact")
      Object bancontact;

      /**
       * This sub-hash contains details about the Card payment method options to pass to the
       * invoice’s PaymentIntent.
       */
      @SerializedName("card")
      Object card;

      /**
       * This sub-hash contains details about the Bank transfer payment method options to pass to
       * the invoice’s PaymentIntent.
       */
      @SerializedName("customer_balance")
      Object customerBalance;

      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /**
       * This sub-hash contains details about the Konbini payment method options to pass to the
       * invoice’s PaymentIntent.
       */
      @SerializedName("konbini")
      Object konbini;

      /**
       * This sub-hash contains details about the SEPA Direct Debit payment method options to pass
       * to the invoice’s PaymentIntent.
       */
      @SerializedName("sepa_debit")
      Object sepaDebit;

      /**
       * This sub-hash contains details about the ACH direct debit payment method options to pass to
       * the invoice’s PaymentIntent.
       */
      @SerializedName("us_bank_account")
      Object usBankAccount;

      private PaymentMethodOptions(
          Object acssDebit,
          Object bancontact,
          Object card,
          Object customerBalance,
          Map<String, Object> extraParams,
          Object konbini,
          Object sepaDebit,
          Object usBankAccount) {
        this.acssDebit = acssDebit;
        this.bancontact = bancontact;
        this.card = card;
        this.customerBalance = customerBalance;
        this.extraParams = extraParams;
        this.konbini = konbini;
        this.sepaDebit = sepaDebit;
        this.usBankAccount = usBankAccount;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Object acssDebit;

        private Object bancontact;

        private Object card;

        private Object customerBalance;

        private Map<String, Object> extraParams;

        private Object konbini;

        private Object sepaDebit;

        private Object usBankAccount;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions build() {
          return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions(
              this.acssDebit,
              this.bancontact,
              this.card,
              this.customerBalance,
              this.extraParams,
              this.konbini,
              this.sepaDebit,
              this.usBankAccount);
        }

        /**
         * This sub-hash contains details about the Canadian pre-authorized debit payment method
         * options to pass to the invoice’s PaymentIntent.
         */
        public Builder setAcssDebit(
            SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit acssDebit) {
          this.acssDebit = acssDebit;
          return this;
        }

        /**
         * This sub-hash contains details about the Canadian pre-authorized debit payment method
         * options to pass to the invoice’s PaymentIntent.
         */
        public Builder setAcssDebit(EmptyParam acssDebit) {
          this.acssDebit = acssDebit;
          return this;
        }

        /**
         * This sub-hash contains details about the Bancontact payment method options to pass to the
         * invoice’s PaymentIntent.
         */
        public Builder setBancontact(
            SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Bancontact bancontact) {
          this.bancontact = bancontact;
          return this;
        }

        /**
         * This sub-hash contains details about the Bancontact payment method options to pass to the
         * invoice’s PaymentIntent.
         */
        public Builder setBancontact(EmptyParam bancontact) {
          this.bancontact = bancontact;
          return this;
        }

        /**
         * This sub-hash contains details about the Card payment method options to pass to the
         * invoice’s PaymentIntent.
         */
        public Builder setCard(
            SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card card) {
          this.card = card;
          return this;
        }

        /**
         * This sub-hash contains details about the Card payment method options to pass to the
         * invoice’s PaymentIntent.
         */
        public Builder setCard(EmptyParam card) {
          this.card = card;
          return this;
        }

        /**
         * This sub-hash contains details about the Bank transfer payment method options to pass to
         * the invoice’s PaymentIntent.
         */
        public Builder setCustomerBalance(
            SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance
                customerBalance) {
          this.customerBalance = customerBalance;
          return this;
        }

        /**
         * This sub-hash contains details about the Bank transfer payment method options to pass to
         * the invoice’s PaymentIntent.
         */
        public Builder setCustomerBalance(EmptyParam customerBalance) {
          this.customerBalance = customerBalance;
          return this;
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link
         * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions#extraParams} for the field
         * documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link
         * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions#extraParams} for the field
         * documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /**
         * This sub-hash contains details about the Konbini payment method options to pass to the
         * invoice’s PaymentIntent.
         */
        public Builder setKonbini(
            SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Konbini konbini) {
          this.konbini = konbini;
          return this;
        }

        /**
         * This sub-hash contains details about the Konbini payment method options to pass to the
         * invoice’s PaymentIntent.
         */
        public Builder setKonbini(EmptyParam konbini) {
          this.konbini = konbini;
          return this;
        }

        /**
         * This sub-hash contains details about the SEPA Direct Debit payment method options to pass
         * to the invoice’s PaymentIntent.
         */
        public Builder setSepaDebit(
            SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.SepaDebit sepaDebit) {
          this.sepaDebit = sepaDebit;
          return this;
        }

        /**
         * This sub-hash contains details about the SEPA Direct Debit payment method options to pass
         * to the invoice’s PaymentIntent.
         */
        public Builder setSepaDebit(EmptyParam sepaDebit) {
          this.sepaDebit = sepaDebit;
          return this;
        }

        /**
         * This sub-hash contains details about the ACH direct debit payment method options to pass
         * to the invoice’s PaymentIntent.
         */
        public Builder setUsBankAccount(
            SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                usBankAccount) {
          this.usBankAccount = usBankAccount;
          return this;
        }

        /**
         * This sub-hash contains details about the ACH direct debit payment method options to pass
         * to the invoice’s PaymentIntent.
         */
        public Builder setUsBankAccount(EmptyParam usBankAccount) {
          this.usBankAccount = usBankAccount;
          return this;
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class AcssDebit {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /** Additional fields for Mandate creation. */
        @SerializedName("mandate_options")
        MandateOptions mandateOptions;

        /** Verification method for the intent. */
        @SerializedName("verification_method")
        VerificationMethod verificationMethod;

        private AcssDebit(
            Map<String, Object> extraParams,
            MandateOptions mandateOptions,
            VerificationMethod verificationMethod) {
          this.extraParams = extraParams;
          this.mandateOptions = mandateOptions;
          this.verificationMethod = verificationMethod;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          private MandateOptions mandateOptions;

          private VerificationMethod verificationMethod;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit build() {
            return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit(
                this.extraParams, this.mandateOptions, this.verificationMethod);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit#extraParams}
           * for the field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit#extraParams}
           * for the field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /** Additional fields for Mandate creation. */
          public Builder setMandateOptions(
              SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit.MandateOptions
                  mandateOptions) {
            this.mandateOptions = mandateOptions;
            return this;
          }

          /** Verification method for the intent. */
          public Builder setVerificationMethod(
              SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit
                      .VerificationMethod
                  verificationMethod) {
            this.verificationMethod = verificationMethod;
            return this;
          }
        }

        @Getter
        @EqualsAndHashCode(callSuper = false)
        public static class MandateOptions {
          /**
           * Map of extra parameters for custom features not available in this client library. The
           * content in this map is not serialized under this field's {@code @SerializedName} value.
           * Instead, each key/value pair is serialized as if the key is a root-level field
           * (serialized) name in this param object. Effectively, this map is flattened to its
           * parent instance.
           */
          @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
          Map<String, Object> extraParams;

          /** Transaction type of the mandate. */
          @SerializedName("transaction_type")
          TransactionType transactionType;

          private MandateOptions(Map<String, Object> extraParams, TransactionType transactionType) {
            this.extraParams = extraParams;
            this.transactionType = transactionType;
          }

          public static Builder builder() {
            return new Builder();
          }

          public static class Builder {
            private Map<String, Object> extraParams;

            private TransactionType transactionType;

            /** Finalize and obtain parameter instance from this builder. */
            public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit
                    .MandateOptions
                build() {
              return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit
                  .MandateOptions(this.extraParams, this.transactionType);
            }

            /**
             * Add a key/value pair to `extraParams` map. A map is initialized for the first
             * `put/putAll` call, and subsequent calls add additional key/value pairs to the
             * original map. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit.MandateOptions#extraParams}
             * for the field documentation.
             */
            public Builder putExtraParam(String key, Object value) {
              if (this.extraParams == null) {
                this.extraParams = new HashMap<>();
              }
              this.extraParams.put(key, value);
              return this;
            }

            /**
             * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
             * `put/putAll` call, and subsequent calls add additional key/value pairs to the
             * original map. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit.MandateOptions#extraParams}
             * for the field documentation.
             */
            public Builder putAllExtraParam(Map<String, Object> map) {
              if (this.extraParams == null) {
                this.extraParams = new HashMap<>();
              }
              this.extraParams.putAll(map);
              return this;
            }

            /** Transaction type of the mandate. */
            public Builder setTransactionType(
                SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.AcssDebit
                        .MandateOptions.TransactionType
                    transactionType) {
              this.transactionType = transactionType;
              return this;
            }
          }

          public enum TransactionType implements ApiRequestParams.EnumParam {
            @SerializedName("business")
            BUSINESS("business"),

            @SerializedName("personal")
            PERSONAL("personal");

            @Getter(onMethod_ = {@Override})
            private final String value;

            TransactionType(String value) {
              this.value = value;
            }
          }
        }

        public enum VerificationMethod implements ApiRequestParams.EnumParam {
          @SerializedName("automatic")
          AUTOMATIC("automatic"),

          @SerializedName("instant")
          INSTANT("instant"),

          @SerializedName("microdeposits")
          MICRODEPOSITS("microdeposits");

          @Getter(onMethod_ = {@Override})
          private final String value;

          VerificationMethod(String value) {
            this.value = value;
          }
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class Bancontact {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /**
         * Preferred language of the Bancontact authorization page that the customer is redirected
         * to.
         */
        @SerializedName("preferred_language")
        PreferredLanguage preferredLanguage;

        private Bancontact(Map<String, Object> extraParams, PreferredLanguage preferredLanguage) {
          this.extraParams = extraParams;
          this.preferredLanguage = preferredLanguage;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          private PreferredLanguage preferredLanguage;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Bancontact build() {
            return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Bancontact(
                this.extraParams, this.preferredLanguage);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Bancontact#extraParams}
           * for the field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Bancontact#extraParams}
           * for the field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /**
           * Preferred language of the Bancontact authorization page that the customer is redirected
           * to.
           */
          public Builder setPreferredLanguage(
              SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Bancontact
                      .PreferredLanguage
                  preferredLanguage) {
            this.preferredLanguage = preferredLanguage;
            return this;
          }
        }

        public enum PreferredLanguage implements ApiRequestParams.EnumParam {
          @SerializedName("de")
          DE("de"),

          @SerializedName("en")
          EN("en"),

          @SerializedName("fr")
          FR("fr"),

          @SerializedName("nl")
          NL("nl");

          @Getter(onMethod_ = {@Override})
          private final String value;

          PreferredLanguage(String value) {
            this.value = value;
          }
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class Card {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /** Configuration options for setting up an eMandate for cards issued in India. */
        @SerializedName("mandate_options")
        MandateOptions mandateOptions;

        /**
         * Selected network to process this Subscription on. Depends on the available networks of
         * the card attached to the Subscription. Can be only set confirm-time.
         */
        @SerializedName("network")
        Network network;

        /**
         * We strongly recommend that you rely on our SCA Engine to automatically prompt your
         * customers for authentication based on risk level and <a
         * href="https://stripe.com/docs/strong-customer-authentication">other requirements</a>.
         * However, if you wish to request 3D Secure based on logic from your own fraud engine,
         * provide this option. Read our guide on <a
         * href="https://stripe.com/docs/payments/3d-secure/authentication-flow#manual-three-ds">manually
         * requesting 3D Secure</a> for more information on how this configuration interacts with
         * Radar and our SCA Engine.
         */
        @SerializedName("request_three_d_secure")
        RequestThreeDSecure requestThreeDSecure;

        private Card(
            Map<String, Object> extraParams,
            MandateOptions mandateOptions,
            Network network,
            RequestThreeDSecure requestThreeDSecure) {
          this.extraParams = extraParams;
          this.mandateOptions = mandateOptions;
          this.network = network;
          this.requestThreeDSecure = requestThreeDSecure;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          private MandateOptions mandateOptions;

          private Network network;

          private RequestThreeDSecure requestThreeDSecure;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card build() {
            return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card(
                this.extraParams, this.mandateOptions, this.network, this.requestThreeDSecure);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card#extraParams} for the
           * field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card#extraParams} for the
           * field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /** Configuration options for setting up an eMandate for cards issued in India. */
          public Builder setMandateOptions(
              SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card.MandateOptions
                  mandateOptions) {
            this.mandateOptions = mandateOptions;
            return this;
          }

          /**
           * Selected network to process this Subscription on. Depends on the available networks of
           * the card attached to the Subscription. Can be only set confirm-time.
           */
          public Builder setNetwork(
              SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card.Network network) {
            this.network = network;
            return this;
          }

          /**
           * We strongly recommend that you rely on our SCA Engine to automatically prompt your
           * customers for authentication based on risk level and <a
           * href="https://stripe.com/docs/strong-customer-authentication">other requirements</a>.
           * However, if you wish to request 3D Secure based on logic from your own fraud engine,
           * provide this option. Read our guide on <a
           * href="https://stripe.com/docs/payments/3d-secure/authentication-flow#manual-three-ds">manually
           * requesting 3D Secure</a> for more information on how this configuration interacts with
           * Radar and our SCA Engine.
           */
          public Builder setRequestThreeDSecure(
              SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card.RequestThreeDSecure
                  requestThreeDSecure) {
            this.requestThreeDSecure = requestThreeDSecure;
            return this;
          }
        }

        @Getter
        @EqualsAndHashCode(callSuper = false)
        public static class MandateOptions {
          /** Amount to be charged for future payments. */
          @SerializedName("amount")
          Long amount;

          /**
           * One of {@code fixed} or {@code maximum}. If {@code fixed}, the {@code amount} param
           * refers to the exact amount to be charged in future payments. If {@code maximum}, the
           * amount charged can be up to the value passed for the {@code amount} param.
           */
          @SerializedName("amount_type")
          AmountType amountType;

          /**
           * A description of the mandate or subscription that is meant to be displayed to the
           * customer.
           */
          @SerializedName("description")
          Object description;

          /**
           * Map of extra parameters for custom features not available in this client library. The
           * content in this map is not serialized under this field's {@code @SerializedName} value.
           * Instead, each key/value pair is serialized as if the key is a root-level field
           * (serialized) name in this param object. Effectively, this map is flattened to its
           * parent instance.
           */
          @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
          Map<String, Object> extraParams;

          private MandateOptions(
              Long amount,
              AmountType amountType,
              Object description,
              Map<String, Object> extraParams) {
            this.amount = amount;
            this.amountType = amountType;
            this.description = description;
            this.extraParams = extraParams;
          }

          public static Builder builder() {
            return new Builder();
          }

          public static class Builder {
            private Long amount;

            private AmountType amountType;

            private Object description;

            private Map<String, Object> extraParams;

            /** Finalize and obtain parameter instance from this builder. */
            public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card.MandateOptions
                build() {
              return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card
                  .MandateOptions(this.amount, this.amountType, this.description, this.extraParams);
            }

            /** Amount to be charged for future payments. */
            public Builder setAmount(Long amount) {
              this.amount = amount;
              return this;
            }

            /**
             * One of {@code fixed} or {@code maximum}. If {@code fixed}, the {@code amount} param
             * refers to the exact amount to be charged in future payments. If {@code maximum}, the
             * amount charged can be up to the value passed for the {@code amount} param.
             */
            public Builder setAmountType(
                SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card.MandateOptions
                        .AmountType
                    amountType) {
              this.amountType = amountType;
              return this;
            }

            /**
             * A description of the mandate or subscription that is meant to be displayed to the
             * customer.
             */
            public Builder setDescription(String description) {
              this.description = description;
              return this;
            }

            /**
             * A description of the mandate or subscription that is meant to be displayed to the
             * customer.
             */
            public Builder setDescription(EmptyParam description) {
              this.description = description;
              return this;
            }

            /**
             * Add a key/value pair to `extraParams` map. A map is initialized for the first
             * `put/putAll` call, and subsequent calls add additional key/value pairs to the
             * original map. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card.MandateOptions#extraParams}
             * for the field documentation.
             */
            public Builder putExtraParam(String key, Object value) {
              if (this.extraParams == null) {
                this.extraParams = new HashMap<>();
              }
              this.extraParams.put(key, value);
              return this;
            }

            /**
             * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
             * `put/putAll` call, and subsequent calls add additional key/value pairs to the
             * original map. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Card.MandateOptions#extraParams}
             * for the field documentation.
             */
            public Builder putAllExtraParam(Map<String, Object> map) {
              if (this.extraParams == null) {
                this.extraParams = new HashMap<>();
              }
              this.extraParams.putAll(map);
              return this;
            }
          }

          public enum AmountType implements ApiRequestParams.EnumParam {
            @SerializedName("fixed")
            FIXED("fixed"),

            @SerializedName("maximum")
            MAXIMUM("maximum");

            @Getter(onMethod_ = {@Override})
            private final String value;

            AmountType(String value) {
              this.value = value;
            }
          }
        }

        public enum Network implements ApiRequestParams.EnumParam {
          @SerializedName("amex")
          AMEX("amex"),

          @SerializedName("cartes_bancaires")
          CARTES_BANCAIRES("cartes_bancaires"),

          @SerializedName("diners")
          DINERS("diners"),

          @SerializedName("discover")
          DISCOVER("discover"),

          @SerializedName("eftpos_au")
          EFTPOS_AU("eftpos_au"),

          @SerializedName("girocard")
          GIROCARD("girocard"),

          @SerializedName("interac")
          INTERAC("interac"),

          @SerializedName("jcb")
          JCB("jcb"),

          @SerializedName("link")
          LINK("link"),

          @SerializedName("mastercard")
          MASTERCARD("mastercard"),

          @SerializedName("unionpay")
          UNIONPAY("unionpay"),

          @SerializedName("unknown")
          UNKNOWN("unknown"),

          @SerializedName("visa")
          VISA("visa");

          @Getter(onMethod_ = {@Override})
          private final String value;

          Network(String value) {
            this.value = value;
          }
        }

        public enum RequestThreeDSecure implements ApiRequestParams.EnumParam {
          @SerializedName("any")
          ANY("any"),

          @SerializedName("automatic")
          AUTOMATIC("automatic"),

          @SerializedName("challenge")
          CHALLENGE("challenge");

          @Getter(onMethod_ = {@Override})
          private final String value;

          RequestThreeDSecure(String value) {
            this.value = value;
          }
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class CustomerBalance {
        /**
         * Configuration for the bank transfer funding type, if the {@code funding_type} is set to
         * {@code bank_transfer}.
         */
        @SerializedName("bank_transfer")
        BankTransfer bankTransfer;

        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /**
         * The funding method type to be used when there are not enough funds in the customer
         * balance. Permitted values include: {@code bank_transfer}.
         */
        @SerializedName("funding_type")
        Object fundingType;

        private CustomerBalance(
            BankTransfer bankTransfer, Map<String, Object> extraParams, Object fundingType) {
          this.bankTransfer = bankTransfer;
          this.extraParams = extraParams;
          this.fundingType = fundingType;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private BankTransfer bankTransfer;

          private Map<String, Object> extraParams;

          private Object fundingType;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance
              build() {
            return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions
                .CustomerBalance(this.bankTransfer, this.extraParams, this.fundingType);
          }

          /**
           * Configuration for the bank transfer funding type, if the {@code funding_type} is set to
           * {@code bank_transfer}.
           */
          public Builder setBankTransfer(
              SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance
                      .BankTransfer
                  bankTransfer) {
            this.bankTransfer = bankTransfer;
            return this;
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance#extraParams}
           * for the field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance#extraParams}
           * for the field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /**
           * The funding method type to be used when there are not enough funds in the customer
           * balance. Permitted values include: {@code bank_transfer}.
           */
          public Builder setFundingType(String fundingType) {
            this.fundingType = fundingType;
            return this;
          }

          /**
           * The funding method type to be used when there are not enough funds in the customer
           * balance. Permitted values include: {@code bank_transfer}.
           */
          public Builder setFundingType(EmptyParam fundingType) {
            this.fundingType = fundingType;
            return this;
          }
        }

        @Getter
        @EqualsAndHashCode(callSuper = false)
        public static class BankTransfer {
          /** Configuration for eu_bank_transfer funding type. */
          @SerializedName("eu_bank_transfer")
          EuBankTransfer euBankTransfer;

          /**
           * Map of extra parameters for custom features not available in this client library. The
           * content in this map is not serialized under this field's {@code @SerializedName} value.
           * Instead, each key/value pair is serialized as if the key is a root-level field
           * (serialized) name in this param object. Effectively, this map is flattened to its
           * parent instance.
           */
          @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
          Map<String, Object> extraParams;

          /**
           * The bank transfer type that can be used for funding. Permitted values include: {@code
           * eu_bank_transfer}, {@code gb_bank_transfer}, {@code jp_bank_transfer}, {@code
           * mx_bank_transfer}, or {@code us_bank_transfer}.
           */
          @SerializedName("type")
          Object type;

          private BankTransfer(
              EuBankTransfer euBankTransfer, Map<String, Object> extraParams, Object type) {
            this.euBankTransfer = euBankTransfer;
            this.extraParams = extraParams;
            this.type = type;
          }

          public static Builder builder() {
            return new Builder();
          }

          public static class Builder {
            private EuBankTransfer euBankTransfer;

            private Map<String, Object> extraParams;

            private Object type;

            /** Finalize and obtain parameter instance from this builder. */
            public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance
                    .BankTransfer
                build() {
              return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions
                  .CustomerBalance.BankTransfer(this.euBankTransfer, this.extraParams, this.type);
            }

            /** Configuration for eu_bank_transfer funding type. */
            public Builder setEuBankTransfer(
                SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance
                        .BankTransfer.EuBankTransfer
                    euBankTransfer) {
              this.euBankTransfer = euBankTransfer;
              return this;
            }

            /**
             * Add a key/value pair to `extraParams` map. A map is initialized for the first
             * `put/putAll` call, and subsequent calls add additional key/value pairs to the
             * original map. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance.BankTransfer#extraParams}
             * for the field documentation.
             */
            public Builder putExtraParam(String key, Object value) {
              if (this.extraParams == null) {
                this.extraParams = new HashMap<>();
              }
              this.extraParams.put(key, value);
              return this;
            }

            /**
             * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
             * `put/putAll` call, and subsequent calls add additional key/value pairs to the
             * original map. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance.BankTransfer#extraParams}
             * for the field documentation.
             */
            public Builder putAllExtraParam(Map<String, Object> map) {
              if (this.extraParams == null) {
                this.extraParams = new HashMap<>();
              }
              this.extraParams.putAll(map);
              return this;
            }

            /**
             * The bank transfer type that can be used for funding. Permitted values include: {@code
             * eu_bank_transfer}, {@code gb_bank_transfer}, {@code jp_bank_transfer}, {@code
             * mx_bank_transfer}, or {@code us_bank_transfer}.
             */
            public Builder setType(String type) {
              this.type = type;
              return this;
            }

            /**
             * The bank transfer type that can be used for funding. Permitted values include: {@code
             * eu_bank_transfer}, {@code gb_bank_transfer}, {@code jp_bank_transfer}, {@code
             * mx_bank_transfer}, or {@code us_bank_transfer}.
             */
            public Builder setType(EmptyParam type) {
              this.type = type;
              return this;
            }
          }

          @Getter
          @EqualsAndHashCode(callSuper = false)
          public static class EuBankTransfer {
            /**
             * <strong>Required.</strong> The desired country code of the bank account information.
             * Permitted values include: {@code BE}, {@code DE}, {@code ES}, {@code FR}, {@code IE},
             * or {@code NL}.
             */
            @SerializedName("country")
            Object country;

            /**
             * Map of extra parameters for custom features not available in this client library. The
             * content in this map is not serialized under this field's {@code @SerializedName}
             * value. Instead, each key/value pair is serialized as if the key is a root-level field
             * (serialized) name in this param object. Effectively, this map is flattened to its
             * parent instance.
             */
            @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
            Map<String, Object> extraParams;

            private EuBankTransfer(Object country, Map<String, Object> extraParams) {
              this.country = country;
              this.extraParams = extraParams;
            }

            public static Builder builder() {
              return new Builder();
            }

            public static class Builder {
              private Object country;

              private Map<String, Object> extraParams;

              /** Finalize and obtain parameter instance from this builder. */
              public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance
                      .BankTransfer.EuBankTransfer
                  build() {
                return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions
                    .CustomerBalance.BankTransfer.EuBankTransfer(this.country, this.extraParams);
              }

              /**
               * <strong>Required.</strong> The desired country code of the bank account
               * information. Permitted values include: {@code BE}, {@code DE}, {@code ES}, {@code
               * FR}, {@code IE}, or {@code NL}.
               */
              public Builder setCountry(String country) {
                this.country = country;
                return this;
              }

              /**
               * <strong>Required.</strong> The desired country code of the bank account
               * information. Permitted values include: {@code BE}, {@code DE}, {@code ES}, {@code
               * FR}, {@code IE}, or {@code NL}.
               */
              public Builder setCountry(EmptyParam country) {
                this.country = country;
                return this;
              }

              /**
               * Add a key/value pair to `extraParams` map. A map is initialized for the first
               * `put/putAll` call, and subsequent calls add additional key/value pairs to the
               * original map. See {@link
               * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance.BankTransfer.EuBankTransfer#extraParams}
               * for the field documentation.
               */
              public Builder putExtraParam(String key, Object value) {
                if (this.extraParams == null) {
                  this.extraParams = new HashMap<>();
                }
                this.extraParams.put(key, value);
                return this;
              }

              /**
               * Add all map key/value pairs to `extraParams` map. A map is initialized for the
               * first `put/putAll` call, and subsequent calls add additional key/value pairs to the
               * original map. See {@link
               * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.CustomerBalance.BankTransfer.EuBankTransfer#extraParams}
               * for the field documentation.
               */
              public Builder putAllExtraParam(Map<String, Object> map) {
                if (this.extraParams == null) {
                  this.extraParams = new HashMap<>();
                }
                this.extraParams.putAll(map);
                return this;
              }
            }
          }
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class Konbini {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        private Konbini(Map<String, Object> extraParams) {
          this.extraParams = extraParams;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Konbini build() {
            return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Konbini(
                this.extraParams);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Konbini#extraParams} for
           * the field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.Konbini#extraParams} for
           * the field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class SepaDebit {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        private SepaDebit(Map<String, Object> extraParams) {
          this.extraParams = extraParams;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.SepaDebit build() {
            return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.SepaDebit(
                this.extraParams);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.SepaDebit#extraParams}
           * for the field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.SepaDebit#extraParams}
           * for the field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }
        }
      }

      @Getter
      @EqualsAndHashCode(callSuper = false)
      public static class UsBankAccount {
        /**
         * Map of extra parameters for custom features not available in this client library. The
         * content in this map is not serialized under this field's {@code @SerializedName} value.
         * Instead, each key/value pair is serialized as if the key is a root-level field
         * (serialized) name in this param object. Effectively, this map is flattened to its parent
         * instance.
         */
        @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
        Map<String, Object> extraParams;

        /** Additional fields for Financial Connections Session creation. */
        @SerializedName("financial_connections")
        FinancialConnections financialConnections;

        /** Verification method for the intent. */
        @SerializedName("verification_method")
        VerificationMethod verificationMethod;

        private UsBankAccount(
            Map<String, Object> extraParams,
            FinancialConnections financialConnections,
            VerificationMethod verificationMethod) {
          this.extraParams = extraParams;
          this.financialConnections = financialConnections;
          this.verificationMethod = verificationMethod;
        }

        public static Builder builder() {
          return new Builder();
        }

        public static class Builder {
          private Map<String, Object> extraParams;

          private FinancialConnections financialConnections;

          private VerificationMethod verificationMethod;

          /** Finalize and obtain parameter instance from this builder. */
          public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
              build() {
            return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount(
                this.extraParams, this.financialConnections, this.verificationMethod);
          }

          /**
           * Add a key/value pair to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount#extraParams}
           * for the field documentation.
           */
          public Builder putExtraParam(String key, Object value) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.put(key, value);
            return this;
          }

          /**
           * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
           * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
           * map. See {@link
           * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount#extraParams}
           * for the field documentation.
           */
          public Builder putAllExtraParam(Map<String, Object> map) {
            if (this.extraParams == null) {
              this.extraParams = new HashMap<>();
            }
            this.extraParams.putAll(map);
            return this;
          }

          /** Additional fields for Financial Connections Session creation. */
          public Builder setFinancialConnections(
              SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                      .FinancialConnections
                  financialConnections) {
            this.financialConnections = financialConnections;
            return this;
          }

          /** Verification method for the intent. */
          public Builder setVerificationMethod(
              SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                      .VerificationMethod
                  verificationMethod) {
            this.verificationMethod = verificationMethod;
            return this;
          }
        }

        @Getter
        @EqualsAndHashCode(callSuper = false)
        public static class FinancialConnections {
          /**
           * Map of extra parameters for custom features not available in this client library. The
           * content in this map is not serialized under this field's {@code @SerializedName} value.
           * Instead, each key/value pair is serialized as if the key is a root-level field
           * (serialized) name in this param object. Effectively, this map is flattened to its
           * parent instance.
           */
          @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
          Map<String, Object> extraParams;

          /**
           * Provide filters for the linked accounts that the customer can select for the payment
           * method.
           */
          @SerializedName("filters")
          Filters filters;

          /**
           * The list of permissions to request. If this parameter is passed, the {@code
           * payment_method} permission must be included. Valid permissions include: {@code
           * balances}, {@code ownership}, {@code payment_method}, and {@code transactions}.
           */
          @SerializedName("permissions")
          List<
                  SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                      .FinancialConnections.Permission>
              permissions;

          /** List of data features that you would like to retrieve upon account creation. */
          @SerializedName("prefetch")
          List<
                  SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                      .FinancialConnections.Prefetch>
              prefetch;

          private FinancialConnections(
              Map<String, Object> extraParams,
              Filters filters,
              List<
                      SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                          .FinancialConnections.Permission>
                  permissions,
              List<
                      SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                          .FinancialConnections.Prefetch>
                  prefetch) {
            this.extraParams = extraParams;
            this.filters = filters;
            this.permissions = permissions;
            this.prefetch = prefetch;
          }

          public static Builder builder() {
            return new Builder();
          }

          public static class Builder {
            private Map<String, Object> extraParams;

            private Filters filters;

            private List<
                    SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                        .FinancialConnections.Permission>
                permissions;

            private List<
                    SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                        .FinancialConnections.Prefetch>
                prefetch;

            /** Finalize and obtain parameter instance from this builder. */
            public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                    .FinancialConnections
                build() {
              return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                  .FinancialConnections(
                  this.extraParams, this.filters, this.permissions, this.prefetch);
            }

            /**
             * Add a key/value pair to `extraParams` map. A map is initialized for the first
             * `put/putAll` call, and subsequent calls add additional key/value pairs to the
             * original map. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections#extraParams}
             * for the field documentation.
             */
            public Builder putExtraParam(String key, Object value) {
              if (this.extraParams == null) {
                this.extraParams = new HashMap<>();
              }
              this.extraParams.put(key, value);
              return this;
            }

            /**
             * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
             * `put/putAll` call, and subsequent calls add additional key/value pairs to the
             * original map. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections#extraParams}
             * for the field documentation.
             */
            public Builder putAllExtraParam(Map<String, Object> map) {
              if (this.extraParams == null) {
                this.extraParams = new HashMap<>();
              }
              this.extraParams.putAll(map);
              return this;
            }

            /**
             * Provide filters for the linked accounts that the customer can select for the payment
             * method.
             */
            public Builder setFilters(
                SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                        .FinancialConnections.Filters
                    filters) {
              this.filters = filters;
              return this;
            }

            /**
             * Add an element to `permissions` list. A list is initialized for the first
             * `add/addAll` call, and subsequent calls adds additional elements to the original
             * list. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections#permissions}
             * for the field documentation.
             */
            public Builder addPermission(
                SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                        .FinancialConnections.Permission
                    element) {
              if (this.permissions == null) {
                this.permissions = new ArrayList<>();
              }
              this.permissions.add(element);
              return this;
            }

            /**
             * Add all elements to `permissions` list. A list is initialized for the first
             * `add/addAll` call, and subsequent calls adds additional elements to the original
             * list. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections#permissions}
             * for the field documentation.
             */
            public Builder addAllPermission(
                List<
                        SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                            .FinancialConnections.Permission>
                    elements) {
              if (this.permissions == null) {
                this.permissions = new ArrayList<>();
              }
              this.permissions.addAll(elements);
              return this;
            }

            /**
             * Add an element to `prefetch` list. A list is initialized for the first `add/addAll`
             * call, and subsequent calls adds additional elements to the original list. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections#prefetch}
             * for the field documentation.
             */
            public Builder addPrefetch(
                SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                        .FinancialConnections.Prefetch
                    element) {
              if (this.prefetch == null) {
                this.prefetch = new ArrayList<>();
              }
              this.prefetch.add(element);
              return this;
            }

            /**
             * Add all elements to `prefetch` list. A list is initialized for the first `add/addAll`
             * call, and subsequent calls adds additional elements to the original list. See {@link
             * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections#prefetch}
             * for the field documentation.
             */
            public Builder addAllPrefetch(
                List<
                        SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                            .FinancialConnections.Prefetch>
                    elements) {
              if (this.prefetch == null) {
                this.prefetch = new ArrayList<>();
              }
              this.prefetch.addAll(elements);
              return this;
            }
          }

          @Getter
          @EqualsAndHashCode(callSuper = false)
          public static class Filters {
            /**
             * The account subcategories to use to filter for selectable accounts. Valid
             * subcategories are {@code checking} and {@code savings}.
             */
            @SerializedName("account_subcategories")
            List<
                    SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                        .FinancialConnections.Filters.AccountSubcategory>
                accountSubcategories;

            /**
             * Map of extra parameters for custom features not available in this client library. The
             * content in this map is not serialized under this field's {@code @SerializedName}
             * value. Instead, each key/value pair is serialized as if the key is a root-level field
             * (serialized) name in this param object. Effectively, this map is flattened to its
             * parent instance.
             */
            @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
            Map<String, Object> extraParams;

            private Filters(
                List<
                        SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                            .FinancialConnections.Filters.AccountSubcategory>
                    accountSubcategories,
                Map<String, Object> extraParams) {
              this.accountSubcategories = accountSubcategories;
              this.extraParams = extraParams;
            }

            public static Builder builder() {
              return new Builder();
            }

            public static class Builder {
              private List<
                      SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                          .FinancialConnections.Filters.AccountSubcategory>
                  accountSubcategories;

              private Map<String, Object> extraParams;

              /** Finalize and obtain parameter instance from this builder. */
              public SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                      .FinancialConnections.Filters
                  build() {
                return new SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions
                    .UsBankAccount.FinancialConnections.Filters(
                    this.accountSubcategories, this.extraParams);
              }

              /**
               * Add an element to `accountSubcategories` list. A list is initialized for the first
               * `add/addAll` call, and subsequent calls adds additional elements to the original
               * list. See {@link
               * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections.Filters#accountSubcategories}
               * for the field documentation.
               */
              public Builder addAccountSubcategory(
                  SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount
                          .FinancialConnections.Filters.AccountSubcategory
                      element) {
                if (this.accountSubcategories == null) {
                  this.accountSubcategories = new ArrayList<>();
                }
                this.accountSubcategories.add(element);
                return this;
              }

              /**
               * Add all elements to `accountSubcategories` list. A list is initialized for the
               * first `add/addAll` call, and subsequent calls adds additional elements to the
               * original list. See {@link
               * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections.Filters#accountSubcategories}
               * for the field documentation.
               */
              public Builder addAllAccountSubcategory(
                  List<
                          SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions
                              .UsBankAccount.FinancialConnections.Filters.AccountSubcategory>
                      elements) {
                if (this.accountSubcategories == null) {
                  this.accountSubcategories = new ArrayList<>();
                }
                this.accountSubcategories.addAll(elements);
                return this;
              }

              /**
               * Add a key/value pair to `extraParams` map. A map is initialized for the first
               * `put/putAll` call, and subsequent calls add additional key/value pairs to the
               * original map. See {@link
               * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections.Filters#extraParams}
               * for the field documentation.
               */
              public Builder putExtraParam(String key, Object value) {
                if (this.extraParams == null) {
                  this.extraParams = new HashMap<>();
                }
                this.extraParams.put(key, value);
                return this;
              }

              /**
               * Add all map key/value pairs to `extraParams` map. A map is initialized for the
               * first `put/putAll` call, and subsequent calls add additional key/value pairs to the
               * original map. See {@link
               * SubscriptionUpdateParams.PaymentSettings.PaymentMethodOptions.UsBankAccount.FinancialConnections.Filters#extraParams}
               * for the field documentation.
               */
              public Builder putAllExtraParam(Map<String, Object> map) {
                if (this.extraParams == null) {
                  this.extraParams = new HashMap<>();
                }
                this.extraParams.putAll(map);
                return this;
              }
            }

            public enum AccountSubcategory implements ApiRequestParams.EnumParam {
              @SerializedName("checking")
              CHECKING("checking"),

              @SerializedName("savings")
              SAVINGS("savings");

              @Getter(onMethod_ = {@Override})
              private final String value;

              AccountSubcategory(String value) {
                this.value = value;
              }
            }
          }

          public enum Permission implements ApiRequestParams.EnumParam {
            @SerializedName("balances")
            BALANCES("balances"),

            @SerializedName("ownership")
            OWNERSHIP("ownership"),

            @SerializedName("payment_method")
            PAYMENT_METHOD("payment_method"),

            @SerializedName("transactions")
            TRANSACTIONS("transactions");

            @Getter(onMethod_ = {@Override})
            private final String value;

            Permission(String value) {
              this.value = value;
            }
          }

          public enum Prefetch implements ApiRequestParams.EnumParam {
            @SerializedName("balances")
            BALANCES("balances"),

            @SerializedName("ownership")
            OWNERSHIP("ownership"),

            @SerializedName("transactions")
            TRANSACTIONS("transactions");

            @Getter(onMethod_ = {@Override})
            private final String value;

            Prefetch(String value) {
              this.value = value;
            }
          }
        }

        public enum VerificationMethod implements ApiRequestParams.EnumParam {
          @SerializedName("automatic")
          AUTOMATIC("automatic"),

          @SerializedName("instant")
          INSTANT("instant"),

          @SerializedName("microdeposits")
          MICRODEPOSITS("microdeposits");

          @Getter(onMethod_ = {@Override})
          private final String value;

          VerificationMethod(String value) {
            this.value = value;
          }
        }
      }
    }

    public enum PaymentMethodType implements ApiRequestParams.EnumParam {
      @SerializedName("ach_credit_transfer")
      ACH_CREDIT_TRANSFER("ach_credit_transfer"),

      @SerializedName("ach_debit")
      ACH_DEBIT("ach_debit"),

      @SerializedName("acss_debit")
      ACSS_DEBIT("acss_debit"),

      @SerializedName("affirm")
      AFFIRM("affirm"),

      @SerializedName("amazon_pay")
      AMAZON_PAY("amazon_pay"),

      @SerializedName("au_becs_debit")
      AU_BECS_DEBIT("au_becs_debit"),

      @SerializedName("bacs_debit")
      BACS_DEBIT("bacs_debit"),

      @SerializedName("bancontact")
      BANCONTACT("bancontact"),

      @SerializedName("boleto")
      BOLETO("boleto"),

      @SerializedName("card")
      CARD("card"),

      @SerializedName("cashapp")
      CASHAPP("cashapp"),

      @SerializedName("crypto")
      CRYPTO("crypto"),

      @SerializedName("custom")
      CUSTOM("custom"),

      @SerializedName("customer_balance")
      CUSTOMER_BALANCE("customer_balance"),

      @SerializedName("eps")
      EPS("eps"),

      @SerializedName("fpx")
      FPX("fpx"),

      @SerializedName("giropay")
      GIROPAY("giropay"),

      @SerializedName("grabpay")
      GRABPAY("grabpay"),

      @SerializedName("ideal")
      IDEAL("ideal"),

      @SerializedName("jp_credit_transfer")
      JP_CREDIT_TRANSFER("jp_credit_transfer"),

      @SerializedName("kakao_pay")
      KAKAO_PAY("kakao_pay"),

      @SerializedName("klarna")
      KLARNA("klarna"),

      @SerializedName("konbini")
      KONBINI("konbini"),

      @SerializedName("kr_card")
      KR_CARD("kr_card"),

      @SerializedName("link")
      LINK("link"),

      @SerializedName("multibanco")
      MULTIBANCO("multibanco"),

      @SerializedName("naver_pay")
      NAVER_PAY("naver_pay"),

      @SerializedName("nz_bank_account")
      NZ_BANK_ACCOUNT("nz_bank_account"),

      @SerializedName("p24")
      P24("p24"),

      @SerializedName("payco")
      PAYCO("payco"),

      @SerializedName("paynow")
      PAYNOW("paynow"),

      @SerializedName("paypal")
      PAYPAL("paypal"),

      @SerializedName("promptpay")
      PROMPTPAY("promptpay"),

      @SerializedName("revolut_pay")
      REVOLUT_PAY("revolut_pay"),

      @SerializedName("sepa_credit_transfer")
      SEPA_CREDIT_TRANSFER("sepa_credit_transfer"),

      @SerializedName("sepa_debit")
      SEPA_DEBIT("sepa_debit"),

      @SerializedName("sofort")
      SOFORT("sofort"),

      @SerializedName("swish")
      SWISH("swish"),

      @SerializedName("us_bank_account")
      US_BANK_ACCOUNT("us_bank_account"),

      @SerializedName("wechat_pay")
      WECHAT_PAY("wechat_pay");

      @Getter(onMethod_ = {@Override})
      private final String value;

      PaymentMethodType(String value) {
        this.value = value;
      }
    }

    public enum SaveDefaultPaymentMethod implements ApiRequestParams.EnumParam {
      @SerializedName("off")
      OFF("off"),

      @SerializedName("on_subscription")
      ON_SUBSCRIPTION("on_subscription");

      @Getter(onMethod_ = {@Override})
      private final String value;

      SaveDefaultPaymentMethod(String value) {
        this.value = value;
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class PendingInvoiceItemInterval {
    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    /**
     * <strong>Required.</strong> Specifies invoicing frequency. Either {@code day}, {@code week},
     * {@code month} or {@code year}.
     */
    @SerializedName("interval")
    Interval interval;

    /**
     * The number of intervals between invoices. For example, {@code interval=month} and {@code
     * interval_count=3} bills every 3 months. Maximum of one year interval allowed (1 year, 12
     * months, or 52 weeks).
     */
    @SerializedName("interval_count")
    Long intervalCount;

    private PendingInvoiceItemInterval(
        Map<String, Object> extraParams, Interval interval, Long intervalCount) {
      this.extraParams = extraParams;
      this.interval = interval;
      this.intervalCount = intervalCount;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private Map<String, Object> extraParams;

      private Interval interval;

      private Long intervalCount;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.PendingInvoiceItemInterval build() {
        return new SubscriptionUpdateParams.PendingInvoiceItemInterval(
            this.extraParams, this.interval, this.intervalCount);
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.PendingInvoiceItemInterval#extraParams} for the field
       * documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.PendingInvoiceItemInterval#extraParams} for the field
       * documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }

      /**
       * <strong>Required.</strong> Specifies invoicing frequency. Either {@code day}, {@code week},
       * {@code month} or {@code year}.
       */
      public Builder setInterval(
          SubscriptionUpdateParams.PendingInvoiceItemInterval.Interval interval) {
        this.interval = interval;
        return this;
      }

      /**
       * The number of intervals between invoices. For example, {@code interval=month} and {@code
       * interval_count=3} bills every 3 months. Maximum of one year interval allowed (1 year, 12
       * months, or 52 weeks).
       */
      public Builder setIntervalCount(Long intervalCount) {
        this.intervalCount = intervalCount;
        return this;
      }
    }

    public enum Interval implements ApiRequestParams.EnumParam {
      @SerializedName("day")
      DAY("day"),

      @SerializedName("month")
      MONTH("month"),

      @SerializedName("week")
      WEEK("week"),

      @SerializedName("year")
      YEAR("year");

      @Getter(onMethod_ = {@Override})
      private final String value;

      Interval(String value) {
        this.value = value;
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class TransferData {
    /**
     * A non-negative decimal between 0 and 100, with at most two decimal places. This represents
     * the percentage of the subscription invoice total that will be transferred to the destination
     * account. By default, the entire amount is transferred to the destination.
     */
    @SerializedName("amount_percent")
    BigDecimal amountPercent;

    /** <strong>Required.</strong> ID of an existing, connected Stripe account. */
    @SerializedName("destination")
    Object destination;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    private TransferData(
        BigDecimal amountPercent, Object destination, Map<String, Object> extraParams) {
      this.amountPercent = amountPercent;
      this.destination = destination;
      this.extraParams = extraParams;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private BigDecimal amountPercent;

      private Object destination;

      private Map<String, Object> extraParams;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.TransferData build() {
        return new SubscriptionUpdateParams.TransferData(
            this.amountPercent, this.destination, this.extraParams);
      }

      /**
       * A non-negative decimal between 0 and 100, with at most two decimal places. This represents
       * the percentage of the subscription invoice total that will be transferred to the
       * destination account. By default, the entire amount is transferred to the destination.
       */
      public Builder setAmountPercent(BigDecimal amountPercent) {
        this.amountPercent = amountPercent;
        return this;
      }

      /** <strong>Required.</strong> ID of an existing, connected Stripe account. */
      public Builder setDestination(String destination) {
        this.destination = destination;
        return this;
      }

      /** <strong>Required.</strong> ID of an existing, connected Stripe account. */
      public Builder setDestination(EmptyParam destination) {
        this.destination = destination;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.TransferData#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.TransferData#extraParams} for the field documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }
    }
  }

  @Getter
  @EqualsAndHashCode(callSuper = false)
  public static class TrialSettings {
    /**
     * <strong>Required.</strong> Defines how the subscription should behave when the user's free
     * trial ends.
     */
    @SerializedName("end_behavior")
    EndBehavior endBehavior;

    /**
     * Map of extra parameters for custom features not available in this client library. The content
     * in this map is not serialized under this field's {@code @SerializedName} value. Instead, each
     * key/value pair is serialized as if the key is a root-level field (serialized) name in this
     * param object. Effectively, this map is flattened to its parent instance.
     */
    @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
    Map<String, Object> extraParams;

    private TrialSettings(EndBehavior endBehavior, Map<String, Object> extraParams) {
      this.endBehavior = endBehavior;
      this.extraParams = extraParams;
    }

    public static Builder builder() {
      return new Builder();
    }

    public static class Builder {
      private EndBehavior endBehavior;

      private Map<String, Object> extraParams;

      /** Finalize and obtain parameter instance from this builder. */
      public SubscriptionUpdateParams.TrialSettings build() {
        return new SubscriptionUpdateParams.TrialSettings(this.endBehavior, this.extraParams);
      }

      /**
       * <strong>Required.</strong> Defines how the subscription should behave when the user's free
       * trial ends.
       */
      public Builder setEndBehavior(
          SubscriptionUpdateParams.TrialSettings.EndBehavior endBehavior) {
        this.endBehavior = endBehavior;
        return this;
      }

      /**
       * Add a key/value pair to `extraParams` map. A map is initialized for the first `put/putAll`
       * call, and subsequent calls add additional key/value pairs to the original map. See {@link
       * SubscriptionUpdateParams.TrialSettings#extraParams} for the field documentation.
       */
      public Builder putExtraParam(String key, Object value) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.put(key, value);
        return this;
      }

      /**
       * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
       * `put/putAll` call, and subsequent calls add additional key/value pairs to the original map.
       * See {@link SubscriptionUpdateParams.TrialSettings#extraParams} for the field documentation.
       */
      public Builder putAllExtraParam(Map<String, Object> map) {
        if (this.extraParams == null) {
          this.extraParams = new HashMap<>();
        }
        this.extraParams.putAll(map);
        return this;
      }
    }

    @Getter
    @EqualsAndHashCode(callSuper = false)
    public static class EndBehavior {
      /**
       * Map of extra parameters for custom features not available in this client library. The
       * content in this map is not serialized under this field's {@code @SerializedName} value.
       * Instead, each key/value pair is serialized as if the key is a root-level field (serialized)
       * name in this param object. Effectively, this map is flattened to its parent instance.
       */
      @SerializedName(ApiRequestParams.EXTRA_PARAMS_KEY)
      Map<String, Object> extraParams;

      /**
       * <strong>Required.</strong> Indicates how the subscription should change when the trial ends
       * if the user did not provide a payment method.
       */
      @SerializedName("missing_payment_method")
      MissingPaymentMethod missingPaymentMethod;

      private EndBehavior(
          Map<String, Object> extraParams, MissingPaymentMethod missingPaymentMethod) {
        this.extraParams = extraParams;
        this.missingPaymentMethod = missingPaymentMethod;
      }

      public static Builder builder() {
        return new Builder();
      }

      public static class Builder {
        private Map<String, Object> extraParams;

        private MissingPaymentMethod missingPaymentMethod;

        /** Finalize and obtain parameter instance from this builder. */
        public SubscriptionUpdateParams.TrialSettings.EndBehavior build() {
          return new SubscriptionUpdateParams.TrialSettings.EndBehavior(
              this.extraParams, this.missingPaymentMethod);
        }

        /**
         * Add a key/value pair to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.TrialSettings.EndBehavior#extraParams} for the
         * field documentation.
         */
        public Builder putExtraParam(String key, Object value) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.put(key, value);
          return this;
        }

        /**
         * Add all map key/value pairs to `extraParams` map. A map is initialized for the first
         * `put/putAll` call, and subsequent calls add additional key/value pairs to the original
         * map. See {@link SubscriptionUpdateParams.TrialSettings.EndBehavior#extraParams} for the
         * field documentation.
         */
        public Builder putAllExtraParam(Map<String, Object> map) {
          if (this.extraParams == null) {
            this.extraParams = new HashMap<>();
          }
          this.extraParams.putAll(map);
          return this;
        }

        /**
         * <strong>Required.</strong> Indicates how the subscription should change when the trial
         * ends if the user did not provide a payment method.
         */
        public Builder setMissingPaymentMethod(
            SubscriptionUpdateParams.TrialSettings.EndBehavior.MissingPaymentMethod
                missingPaymentMethod) {
          this.missingPaymentMethod = missingPaymentMethod;
          return this;
        }
      }

      public enum MissingPaymentMethod implements ApiRequestParams.EnumParam {
        @SerializedName("cancel")
        CANCEL("cancel"),

        @SerializedName("create_invoice")
        CREATE_INVOICE("create_invoice"),

        @SerializedName("pause")
        PAUSE("pause");

        @Getter(onMethod_ = {@Override})
        private final String value;

        MissingPaymentMethod(String value) {
          this.value = value;
        }
      }
    }
  }

  public enum BillingCycleAnchor implements ApiRequestParams.EnumParam {
    @SerializedName("now")
    NOW("now"),

    @SerializedName("unchanged")
    UNCHANGED("unchanged");

    @Getter(onMethod_ = {@Override})
    private final String value;

    BillingCycleAnchor(String value) {
      this.value = value;
    }
  }

  public enum CancelAt implements ApiRequestParams.EnumParam {
    @SerializedName("max_period_end")
    MAX_PERIOD_END("max_period_end"),

    @SerializedName("min_period_end")
    MIN_PERIOD_END("min_period_end");

    @Getter(onMethod_ = {@Override})
    private final String value;

    CancelAt(String value) {
      this.value = value;
    }
  }

  public enum CollectionMethod implements ApiRequestParams.EnumParam {
    @SerializedName("charge_automatically")
    CHARGE_AUTOMATICALLY("charge_automatically"),

    @SerializedName("send_invoice")
    SEND_INVOICE("send_invoice");

    @Getter(onMethod_ = {@Override})
    private final String value;

    CollectionMethod(String value) {
      this.value = value;
    }
  }

  public enum PaymentBehavior implements ApiRequestParams.EnumParam {
    @SerializedName("allow_incomplete")
    ALLOW_INCOMPLETE("allow_incomplete"),

    @SerializedName("default_incomplete")
    DEFAULT_INCOMPLETE("default_incomplete"),

    @SerializedName("error_if_incomplete")
    ERROR_IF_INCOMPLETE("error_if_incomplete"),

    @SerializedName("pending_if_incomplete")
    PENDING_IF_INCOMPLETE("pending_if_incomplete");

    @Getter(onMethod_ = {@Override})
    private final String value;

    PaymentBehavior(String value) {
      this.value = value;
    }
  }

  public enum ProrationBehavior implements ApiRequestParams.EnumParam {
    @SerializedName("always_invoice")
    ALWAYS_INVOICE("always_invoice"),

    @SerializedName("create_prorations")
    CREATE_PRORATIONS("create_prorations"),

    @SerializedName("none")
    NONE("none");

    @Getter(onMethod_ = {@Override})
    private final String value;

    ProrationBehavior(String value) {
      this.value = value;
    }
  }

  public enum TrialEnd implements ApiRequestParams.EnumParam {
    @SerializedName("now")
    NOW("now");

    @Getter(onMethod_ = {@Override})
    private final String value;

    TrialEnd(String value) {
      this.value = value;
    }
  }
}
